[PATCH 2/3] mailbox: zynqmp: Move buffered IPI setup to of_match selected routine

Michal Simek michal.simek at amd.com
Wed Dec 20 05:23:38 PST 2023



On 12/14/23 22:13, Ben Levinsky wrote:
> 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 at amd.com>
> ---
>   drivers/mailbox/zynqmp-ipi-mailbox.c | 124 +++++++++++++++++++--------
>   1 file changed, 89 insertions(+), 35 deletions(-)
> 
> diff --git a/drivers/mailbox/zynqmp-ipi-mailbox.c b/drivers/mailbox/zynqmp-ipi-mailbox.c
> index 2c10aa01b3bb..edefb80a6e47 100644
> --- a/drivers/mailbox/zynqmp-ipi-mailbox.c
> +++ b/drivers/mailbox/zynqmp-ipi-mailbox.c
> @@ -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.
> @@ -82,6 +86,7 @@ struct zynqmp_ipi_mchan {
>    * @mbox:                 mailbox Controller
>    * @mchans:               array for channels, tx channel and rx channel.
>    * @irq:                  IPI agent interrupt ID
> + * setup_ipi_fn:          Function Pointer to set up IPI Channels

Here should be @setup_ipi_fn.

>    */
>   struct zynqmp_ipi_mbox {
>   	struct zynqmp_ipi_pdata *pdata;
> @@ -89,6 +94,7 @@ struct zynqmp_ipi_mbox {
>   	u32 remote_id;
>   	struct mbox_controller mbox;
>   	struct zynqmp_ipi_mchan mchans[2];
> +	setup_ipi_fn setup_ipi_fn;
>   };
>   
>   /**
> @@ -466,12 +472,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;
> @@ -491,6 +494,75 @@ 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;
> +	struct device *dev;

nit: you can put it to the same line mdev, dev.

> +	const char *name;
> +	int ret;
> +
> +	mdev = &ipi_mbox->dev;
> +	dev = ipi_mbox->pdata->dev;
> +
>   	mchan = &ipi_mbox->mchans[IPI_MB_CHNL_TX];
>   	name = "local_request_region";
>   	ret = zynqmp_ipi_mbox_get_buf_res(node, name, &res);
> @@ -565,37 +637,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;
>   }
>   
>   /**
> @@ -626,6 +668,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) {
> @@ -646,9 +689,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);
> @@ -694,7 +746,9 @@ static int 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);


M



More information about the linux-arm-kernel mailing list