All of lore.kernel.org
 help / color / mirror / Atom feed
From: michal.simek@xilinx.com (Michal Simek)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 1/3] mailbox: Adding driver for Xilinx LogiCORE IP mailbox.
Date: Fri, 22 May 2015 09:08:06 +0200	[thread overview]
Message-ID: <555ED5D6.2080600@xilinx.com> (raw)
In-Reply-To: <1432251450-26352-2-git-send-email-moritz.fischer@ettus.com>

On 05/22/2015 01:37 AM, Moritz Fischer wrote:
> The Xilinx LogiCORE IP mailbox is a FPGA core that allows for
> interprocessor communication via AXI4 memory mapped / AXI4 stream
> interfaces.
> 
> It is single channel per core and allows for transmit and receive.
> 
> Signed-off-by: Moritz Fischer <moritz.fischer@ettus.com>
> ---
>  drivers/mailbox/Kconfig          |   8 +
>  drivers/mailbox/Makefile         |   2 +
>  drivers/mailbox/mailbox-xilinx.c | 339 ++++++++++++++++++++++++++++++++++
>  3 files changed, 349 insertions(+)
> 
> diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
> index 84b0a2d..e11e4b2 100644
> --- a/drivers/mailbox/Kconfig
> +++ b/drivers/mailbox/Kconfig
> @@ -60,4 +60,12 @@ config ALTERA_MBOX
>  	  An implementation of the Altera Mailbox soft core. It is used
>  	  to send message between processors. Say Y here if you want to use the
>  	  Altera mailbox support.
> +
> +config XILINX_MBOX
> +	tristate "Xilinx Mailbox"
> +	help
> +	  An implementation of the Xilinx Mailbox soft core. It is used
> +	  to send message between processors. Say Y here if you want to use the
> +	  Xilinx mailbox support.
> +
>  endif
> diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
> index b18201e..d28a028 100644
> --- a/drivers/mailbox/Makefile
> +++ b/drivers/mailbox/Makefile
> @@ -11,3 +11,5 @@ obj-$(CONFIG_OMAP2PLUS_MBOX)	+= omap-mailbox.o
>  obj-$(CONFIG_PCC)		+= pcc.o
>  
>  obj-$(CONFIG_ALTERA_MBOX)	+= mailbox-altera.o
> +
> +obj-$(CONFIG_XILINX_MBOX)	+= mailbox-xilinx.o
> diff --git a/drivers/mailbox/mailbox-xilinx.c b/drivers/mailbox/mailbox-xilinx.c
> new file mode 100644
> index 0000000..8d8aa17
> --- /dev/null
> +++ b/drivers/mailbox/mailbox-xilinx.c
> @@ -0,0 +1,339 @@
> +/*
> + * Copyright (c) 2015, National Instruments Corp. All rights reserved.
> + *
> + * Driver for the Xilinx Logicore mailbox IP block
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; version 2 of the License.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/device.h>
> +#include <linux/interrupt.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/mailbox_controller.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +
> +#define DRIVER_NAME "xilinx-mailbox"
> +
> +/* register offsets */
> +#define MAILBOX_REG_WRDATA 0x00

I prefer to use #define<space>macro_name<tab>value
but up to you.

> +#define MAILBOX_REG_RDDATA 0x08
> +#define MAILBOX_REG_STATUS 0x10
> +#define MAILBOX_REG_ERROR 0x14
> +#define MAILBOX_REG_SIT 0x18
> +#define MAILBOX_REG_RIT 0x1c
> +#define MAILBOX_REG_IS 0x20
> +#define MAILBOX_REG_IE 0x24
> +#define MAILBOX_REG_IP 0x28
> +
> +/* status register */
> +#define STS_RTA BIT(3)
> +#define STS_STA BIT(2)
> +#define STS_FULL BIT(1)
> +#define STS_EMPTY BIT(0)
> +
> +/* error register */
> +#define ERR_FULL BIT(1)
> +#define ERR_EMPTY BIT(0)
> +
> +/* mailbox interrupt status register */
> +#define INT_STATUS_ERR BIT(2)
> +#define INT_STATUS_RTI BIT(1)
> +#define INT_STATUS_STI BIT(0)
> +
> +/* mailbox interrupt enable register */
> +#define INT_ENABLE_ERR BIT(2)
> +#define INT_ENABLE_RTI BIT(1)
> +#define INT_ENABLE_STI BIT(0)
> +
> +#define MBOX_POLLING_MS		5	/* polling interval 5ms */

and you are using tab here - it looks like c&p from somewhere. :-)

> +
> +struct xilinx_mbox {
> +	bool intr_mode;

look below.

> +	int irq;
> +	void __iomem *mbox_base;
> +	struct device *dev;
> +	struct mbox_controller controller;
> +
> +	/* if the controller supports only RX polling mode */
> +	struct timer_list rxpoll_timer;
> +};
> +
> +static struct xilinx_mbox *mbox_chan_to_xilinx_mbox(struct mbox_chan *chan)
> +{
> +	if (!chan || !chan->con_priv)
> +		return NULL;
> +
> +	return (struct xilinx_mbox *)chan->con_priv;
> +}
> +
> +static inline int xilinx_mbox_full(struct xilinx_mbox *mbox)
> +{
> +	u32 status;
> +
> +	status = readl_relaxed(mbox->mbox_base + MAILBOX_REG_STATUS);

empty line here please for easier reading.

> +	return status & STS_FULL;
> +}
> +
> +static inline int xilinx_mbox_pending(struct xilinx_mbox *mbox)
> +{
> +	u32 status;
> +
> +	status = readl_relaxed(mbox->mbox_base + MAILBOX_REG_STATUS);

ditto.

> +	return !(status & STS_EMPTY);
> +}
> +
> +static void xilinx_mbox_rx_intmask(struct xilinx_mbox *mbox, bool enable)
> +{
> +	u32 mask;
> +
> +	mask = readl_relaxed(mbox->mbox_base + MAILBOX_REG_IE);
> +	if (enable)
> +		mask |= INT_ENABLE_RTI;
> +	else
> +		mask &= ~INT_ENABLE_RTI;
> +	writel_relaxed(mask, mbox->mbox_base + MAILBOX_REG_IE);
> +}
> +
> +static void xilinx_mbox_tx_intmask(struct xilinx_mbox *mbox, bool enable)
> +{
> +	u32 mask;
> +
> +	mask = readl_relaxed(mbox->mbox_base + MAILBOX_REG_IE);
> +	if (enable)
> +		mask |= INT_ENABLE_STI;
> +	else
> +		mask &= ~INT_ENABLE_STI;
> +	writel_relaxed(mask, mbox->mbox_base + MAILBOX_REG_IE);
> +}
> +
> +static void xilinx_mbox_rx_data(struct mbox_chan *chan)
> +{
> +	struct xilinx_mbox *mbox = mbox_chan_to_xilinx_mbox(chan);
> +	u32 data;
> +
> +	if (xilinx_mbox_pending(mbox)) {
> +		data = readl_relaxed(mbox->mbox_base + MAILBOX_REG_RDDATA);
> +		mbox_chan_received_data(chan, (void *)data);
> +	}
> +}
> +
> +static void xilinx_mbox_poll_rx(unsigned long data)
> +{
> +	struct mbox_chan *chan = (struct mbox_chan *)data;
> +	struct xilinx_mbox *mbox = mbox_chan_to_xilinx_mbox(chan);
> +
> +	xilinx_mbox_rx_data(chan);
> +
> +	mod_timer(&mbox->rxpoll_timer,
> +		  jiffies + msecs_to_jiffies(MBOX_POLLING_MS));
> +}
> +
> +static irqreturn_t xilinx_mbox_interrupt(int irq, void *p)
> +{
> +	u32 mask;
> +	struct mbox_chan *chan = (struct mbox_chan *)p;
> +	struct xilinx_mbox *mbox = mbox_chan_to_xilinx_mbox(chan);
> +
> +	mask = readl_relaxed(mbox->mbox_base + MAILBOX_REG_IS);
> +	if (mask & INT_STATUS_RTI)
> +		xilinx_mbox_rx_data(chan);
> +
> +	/* mask irqs *before* notifying done, require tx_block=true */
> +	if (mask & INT_STATUS_STI) {
> +		xilinx_mbox_tx_intmask(mbox, false);
> +		mbox_chan_txdone(chan, 0);
> +	}
> +
> +	if (mask & INT_STATUS_ERR)
> +		dev_err(mbox->dev, "Got error IRQ!\n");
> +
> +	writel_relaxed(mask, mbox->mbox_base + MAILBOX_REG_IS);

one more empty line here.

> +	return IRQ_HANDLED;
> +}
> +
> +static int xilinx_mbox_startup(struct mbox_chan *chan)
> +{
> +	int ret;
> +	struct xilinx_mbox *mbox = mbox_chan_to_xilinx_mbox(chan);
> +
> +	if (mbox->intr_mode) {

look below

> +		ret = request_irq(mbox->irq, xilinx_mbox_interrupt, 0,
> +				  dev_name(mbox->dev), chan);
> +		if (unlikely(ret)) {
> +			dev_err(mbox->dev,
> +				"failed to register mailbox interrupt:%d\n",
> +				ret);
> +			mbox->intr_mode = false;
> +			goto polling; /* use polling if failed */
> +		}
> +
> +		xilinx_mbox_rx_intmask(mbox, true);

Are you also setting up polling timer for interrupt mode?
Or here should be return?

> +	}
> +
> +polling:
> +	/* setup polling timer */
> +	setup_timer(&mbox->rxpoll_timer, xilinx_mbox_poll_rx,
> +		    (unsigned long)chan);
> +	mod_timer(&mbox->rxpoll_timer,
> +		  jiffies + msecs_to_jiffies(MBOX_POLLING_MS));
> +
> +	return 0;
> +}
> +
> +static int xilinx_mbox_send_data(struct mbox_chan *chan, void *data)
> +{
> +	struct xilinx_mbox *mbox = mbox_chan_to_xilinx_mbox(chan);
> +	u32 *udata = (u32 *)data;
> +
> +	if (!mbox || !data)
> +		return -EINVAL;
> +
> +	if (xilinx_mbox_full(mbox))
> +		return -EBUSY;
> +
> +	/* enable interrupt before send */
> +	if (mbox->intr_mode)
> +		xilinx_mbox_tx_intmask(mbox, true);
> +
> +	writel_relaxed(*udata, mbox->mbox_base + MAILBOX_REG_WRDATA);
> +
> +	return 0;
> +}
> +
> +static bool xilinx_mbox_last_tx_done(struct mbox_chan *chan)
> +{
> +	struct xilinx_mbox *mbox = mbox_chan_to_xilinx_mbox(chan);
> +
> +	/* return false if mailbox is full */
> +	return xilinx_mbox_full(mbox) ? false : true;
> +}
> +
> +static bool xilinx_mbox_peek_data(struct mbox_chan *chan)
> +{
> +	struct xilinx_mbox *mbox = mbox_chan_to_xilinx_mbox(chan);
> +
> +	return xilinx_mbox_pending(mbox) ? true : false;
> +}
> +
> +static void xilinx_mbox_shutdown(struct mbox_chan *chan)
> +{
> +	struct xilinx_mbox *mbox = mbox_chan_to_xilinx_mbox(chan);
> +
> +	if (mbox->intr_mode) {
> +		/* unmask all interrupt masks */
> +		writel_relaxed(~0, mbox->mbox_base + MAILBOX_REG_IE);
> +		free_irq(mbox->irq, chan);
> +	} else
> +		del_timer_sync(&mbox->rxpoll_timer);

Also {} around else part.

> +}
> +
> +static struct mbox_chan_ops xilinx_mbox_ops = {
> +	.send_data = xilinx_mbox_send_data,
> +	.startup = xilinx_mbox_startup,
> +	.shutdown = xilinx_mbox_shutdown,
> +	.last_tx_done = xilinx_mbox_last_tx_done,
> +	.peek_data = xilinx_mbox_peek_data,
> +};
> +
> +static int xilinx_mbox_probe(struct platform_device *pdev)
> +{
> +	struct xilinx_mbox *mbox;
> +	struct resource	*regs;
> +	struct mbox_chan *chans;
> +	int ret;
> +
> +	mbox = devm_kzalloc(&pdev->dev, sizeof(*mbox),
> +			    GFP_KERNEL);

it should fit to one line - no reason for this indentation.

> +	if (!mbox)
> +		return -ENOMEM;
> +
> +	/* allocated one channel */
> +	chans = devm_kzalloc(&pdev->dev, sizeof(*chans), GFP_KERNEL);
> +	if (!chans)
> +		return -ENOMEM;
> +
> +	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +
> +	mbox->mbox_base = devm_ioremap_resource(&pdev->dev, regs);
> +	if (IS_ERR(mbox->mbox_base))
> +		return PTR_ERR(mbox->mbox_base);
> +
> +	mbox->irq = platform_get_irq(pdev, 0);
> +	/* if irq is present, we can use it, otherwise, poll */
> +	if (mbox->irq >= 0)
> +		mbox->intr_mode = true;
> +	else
> +		dev_info(&pdev->dev, "IRQ not found, fallback to polling.\n");

Is mbox->intr_mode needed at all?
You can simple detect it from mbox->irq anytime.


> +
> +	mbox->dev = &pdev->dev;
> +
> +	/* Hardware supports only one channel. */
> +	chans[0].con_priv = mbox;
> +	mbox->controller.dev = mbox->dev;
> +	mbox->controller.num_chans = 1;
> +	mbox->controller.chans = chans;
> +	mbox->controller.ops = &xilinx_mbox_ops;
> +
> +	if (mbox->intr_mode) {
> +		mbox->controller.txdone_irq = true;
> +	} else {
> +		mbox->controller.txdone_poll = true;
> +		mbox->controller.txpoll_period = MBOX_POLLING_MS;
> +	}

why is this in the different block? Just put it together with above
error message.

> +
> +	ret = mbox_controller_register(&mbox->controller);
> +	if (ret) {
> +		dev_err(&pdev->dev, "Register mailbox failed\n");
> +		goto err;

Just return ret here

> +	}
> +
> +	platform_set_drvdata(pdev, mbox);
> +err:
> +	return ret;

return 0;

> +}
> +
> +
> +static int xilinx_mbox_remove(struct platform_device *pdev)
> +{
> +	struct xilinx_mbox *mbox = platform_get_drvdata(pdev);
> +
> +	if (!mbox)
> +		return -EINVAL;
> +
> +	mbox_controller_unregister(&mbox->controller);
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id xilinx_mbox_match[] = {
> +	{ .compatible = "xlnx,mailbox-2.1" },
> +	{ /* Sentinel */ }
> +};
> +
> +MODULE_DEVICE_TABLE(of, xilinx_mbox_match);
> +
> +static struct platform_driver xilinx_mbox_driver = {
> +	.probe	= xilinx_mbox_probe,
> +	.remove	= xilinx_mbox_remove,
> +	.driver	= {
> +		.name	= DRIVER_NAME,
> +		.of_match_table	= xilinx_mbox_match,
> +	},
> +};
> +
> +module_platform_driver(xilinx_mbox_driver);
> +
> +MODULE_LICENSE("GPL v2");
> +MODULE_DESCRIPTION("Xilinx mailbox specific functions");
> +MODULE_AUTHOR("Moritz Fischer <moritz.fischer@ettus.com>");
> +MODULE_ALIAS("platform:xilinx-mailbox");

This is fine but have you tested it as a plain platform driver?

Thanks,
Michal

WARNING: multiple messages have this Message-ID (diff)
From: Michal Simek <michal.simek@xilinx.com>
To: Moritz Fischer <moritz.fischer@ettus.com>, jassisinghbrar@gmail.com
Cc: linux-kernel@vger.kernel.org, robh+dt@kernel.org,
	pawel.moll@arm.com, mark.rutland@arm.com,
	ijc+devicetree@hellion.org.uk, galak@codeaurora.org,
	michal.simek@xilinx.com, soren.brinkmann@xilinx.com,
	akpm@linux-foundation.org, gregkh@linuxfoundation.org,
	mchehab@osg.samsung.com, arnd@arndb.de, joe@perches.com,
	jingoohan1@gmail.com, devicetree@vger.kernel.org,
	linux-arm-kernel@lists.infradead.org
Subject: Re: [PATCH 1/3] mailbox: Adding driver for Xilinx LogiCORE IP mailbox.
Date: Fri, 22 May 2015 09:08:06 +0200	[thread overview]
Message-ID: <555ED5D6.2080600@xilinx.com> (raw)
In-Reply-To: <1432251450-26352-2-git-send-email-moritz.fischer@ettus.com>

On 05/22/2015 01:37 AM, Moritz Fischer wrote:
> The Xilinx LogiCORE IP mailbox is a FPGA core that allows for
> interprocessor communication via AXI4 memory mapped / AXI4 stream
> interfaces.
> 
> It is single channel per core and allows for transmit and receive.
> 
> Signed-off-by: Moritz Fischer <moritz.fischer@ettus.com>
> ---
>  drivers/mailbox/Kconfig          |   8 +
>  drivers/mailbox/Makefile         |   2 +
>  drivers/mailbox/mailbox-xilinx.c | 339 ++++++++++++++++++++++++++++++++++
>  3 files changed, 349 insertions(+)
> 
> diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
> index 84b0a2d..e11e4b2 100644
> --- a/drivers/mailbox/Kconfig
> +++ b/drivers/mailbox/Kconfig
> @@ -60,4 +60,12 @@ config ALTERA_MBOX
>  	  An implementation of the Altera Mailbox soft core. It is used
>  	  to send message between processors. Say Y here if you want to use the
>  	  Altera mailbox support.
> +
> +config XILINX_MBOX
> +	tristate "Xilinx Mailbox"
> +	help
> +	  An implementation of the Xilinx Mailbox soft core. It is used
> +	  to send message between processors. Say Y here if you want to use the
> +	  Xilinx mailbox support.
> +
>  endif
> diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
> index b18201e..d28a028 100644
> --- a/drivers/mailbox/Makefile
> +++ b/drivers/mailbox/Makefile
> @@ -11,3 +11,5 @@ obj-$(CONFIG_OMAP2PLUS_MBOX)	+= omap-mailbox.o
>  obj-$(CONFIG_PCC)		+= pcc.o
>  
>  obj-$(CONFIG_ALTERA_MBOX)	+= mailbox-altera.o
> +
> +obj-$(CONFIG_XILINX_MBOX)	+= mailbox-xilinx.o
> diff --git a/drivers/mailbox/mailbox-xilinx.c b/drivers/mailbox/mailbox-xilinx.c
> new file mode 100644
> index 0000000..8d8aa17
> --- /dev/null
> +++ b/drivers/mailbox/mailbox-xilinx.c
> @@ -0,0 +1,339 @@
> +/*
> + * Copyright (c) 2015, National Instruments Corp. All rights reserved.
> + *
> + * Driver for the Xilinx Logicore mailbox IP block
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; version 2 of the License.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/device.h>
> +#include <linux/interrupt.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/mailbox_controller.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +
> +#define DRIVER_NAME "xilinx-mailbox"
> +
> +/* register offsets */
> +#define MAILBOX_REG_WRDATA 0x00

I prefer to use #define<space>macro_name<tab>value
but up to you.

> +#define MAILBOX_REG_RDDATA 0x08
> +#define MAILBOX_REG_STATUS 0x10
> +#define MAILBOX_REG_ERROR 0x14
> +#define MAILBOX_REG_SIT 0x18
> +#define MAILBOX_REG_RIT 0x1c
> +#define MAILBOX_REG_IS 0x20
> +#define MAILBOX_REG_IE 0x24
> +#define MAILBOX_REG_IP 0x28
> +
> +/* status register */
> +#define STS_RTA BIT(3)
> +#define STS_STA BIT(2)
> +#define STS_FULL BIT(1)
> +#define STS_EMPTY BIT(0)
> +
> +/* error register */
> +#define ERR_FULL BIT(1)
> +#define ERR_EMPTY BIT(0)
> +
> +/* mailbox interrupt status register */
> +#define INT_STATUS_ERR BIT(2)
> +#define INT_STATUS_RTI BIT(1)
> +#define INT_STATUS_STI BIT(0)
> +
> +/* mailbox interrupt enable register */
> +#define INT_ENABLE_ERR BIT(2)
> +#define INT_ENABLE_RTI BIT(1)
> +#define INT_ENABLE_STI BIT(0)
> +
> +#define MBOX_POLLING_MS		5	/* polling interval 5ms */

and you are using tab here - it looks like c&p from somewhere. :-)

> +
> +struct xilinx_mbox {
> +	bool intr_mode;

look below.

> +	int irq;
> +	void __iomem *mbox_base;
> +	struct device *dev;
> +	struct mbox_controller controller;
> +
> +	/* if the controller supports only RX polling mode */
> +	struct timer_list rxpoll_timer;
> +};
> +
> +static struct xilinx_mbox *mbox_chan_to_xilinx_mbox(struct mbox_chan *chan)
> +{
> +	if (!chan || !chan->con_priv)
> +		return NULL;
> +
> +	return (struct xilinx_mbox *)chan->con_priv;
> +}
> +
> +static inline int xilinx_mbox_full(struct xilinx_mbox *mbox)
> +{
> +	u32 status;
> +
> +	status = readl_relaxed(mbox->mbox_base + MAILBOX_REG_STATUS);

empty line here please for easier reading.

> +	return status & STS_FULL;
> +}
> +
> +static inline int xilinx_mbox_pending(struct xilinx_mbox *mbox)
> +{
> +	u32 status;
> +
> +	status = readl_relaxed(mbox->mbox_base + MAILBOX_REG_STATUS);

ditto.

> +	return !(status & STS_EMPTY);
> +}
> +
> +static void xilinx_mbox_rx_intmask(struct xilinx_mbox *mbox, bool enable)
> +{
> +	u32 mask;
> +
> +	mask = readl_relaxed(mbox->mbox_base + MAILBOX_REG_IE);
> +	if (enable)
> +		mask |= INT_ENABLE_RTI;
> +	else
> +		mask &= ~INT_ENABLE_RTI;
> +	writel_relaxed(mask, mbox->mbox_base + MAILBOX_REG_IE);
> +}
> +
> +static void xilinx_mbox_tx_intmask(struct xilinx_mbox *mbox, bool enable)
> +{
> +	u32 mask;
> +
> +	mask = readl_relaxed(mbox->mbox_base + MAILBOX_REG_IE);
> +	if (enable)
> +		mask |= INT_ENABLE_STI;
> +	else
> +		mask &= ~INT_ENABLE_STI;
> +	writel_relaxed(mask, mbox->mbox_base + MAILBOX_REG_IE);
> +}
> +
> +static void xilinx_mbox_rx_data(struct mbox_chan *chan)
> +{
> +	struct xilinx_mbox *mbox = mbox_chan_to_xilinx_mbox(chan);
> +	u32 data;
> +
> +	if (xilinx_mbox_pending(mbox)) {
> +		data = readl_relaxed(mbox->mbox_base + MAILBOX_REG_RDDATA);
> +		mbox_chan_received_data(chan, (void *)data);
> +	}
> +}
> +
> +static void xilinx_mbox_poll_rx(unsigned long data)
> +{
> +	struct mbox_chan *chan = (struct mbox_chan *)data;
> +	struct xilinx_mbox *mbox = mbox_chan_to_xilinx_mbox(chan);
> +
> +	xilinx_mbox_rx_data(chan);
> +
> +	mod_timer(&mbox->rxpoll_timer,
> +		  jiffies + msecs_to_jiffies(MBOX_POLLING_MS));
> +}
> +
> +static irqreturn_t xilinx_mbox_interrupt(int irq, void *p)
> +{
> +	u32 mask;
> +	struct mbox_chan *chan = (struct mbox_chan *)p;
> +	struct xilinx_mbox *mbox = mbox_chan_to_xilinx_mbox(chan);
> +
> +	mask = readl_relaxed(mbox->mbox_base + MAILBOX_REG_IS);
> +	if (mask & INT_STATUS_RTI)
> +		xilinx_mbox_rx_data(chan);
> +
> +	/* mask irqs *before* notifying done, require tx_block=true */
> +	if (mask & INT_STATUS_STI) {
> +		xilinx_mbox_tx_intmask(mbox, false);
> +		mbox_chan_txdone(chan, 0);
> +	}
> +
> +	if (mask & INT_STATUS_ERR)
> +		dev_err(mbox->dev, "Got error IRQ!\n");
> +
> +	writel_relaxed(mask, mbox->mbox_base + MAILBOX_REG_IS);

one more empty line here.

> +	return IRQ_HANDLED;
> +}
> +
> +static int xilinx_mbox_startup(struct mbox_chan *chan)
> +{
> +	int ret;
> +	struct xilinx_mbox *mbox = mbox_chan_to_xilinx_mbox(chan);
> +
> +	if (mbox->intr_mode) {

look below

> +		ret = request_irq(mbox->irq, xilinx_mbox_interrupt, 0,
> +				  dev_name(mbox->dev), chan);
> +		if (unlikely(ret)) {
> +			dev_err(mbox->dev,
> +				"failed to register mailbox interrupt:%d\n",
> +				ret);
> +			mbox->intr_mode = false;
> +			goto polling; /* use polling if failed */
> +		}
> +
> +		xilinx_mbox_rx_intmask(mbox, true);

Are you also setting up polling timer for interrupt mode?
Or here should be return?

> +	}
> +
> +polling:
> +	/* setup polling timer */
> +	setup_timer(&mbox->rxpoll_timer, xilinx_mbox_poll_rx,
> +		    (unsigned long)chan);
> +	mod_timer(&mbox->rxpoll_timer,
> +		  jiffies + msecs_to_jiffies(MBOX_POLLING_MS));
> +
> +	return 0;
> +}
> +
> +static int xilinx_mbox_send_data(struct mbox_chan *chan, void *data)
> +{
> +	struct xilinx_mbox *mbox = mbox_chan_to_xilinx_mbox(chan);
> +	u32 *udata = (u32 *)data;
> +
> +	if (!mbox || !data)
> +		return -EINVAL;
> +
> +	if (xilinx_mbox_full(mbox))
> +		return -EBUSY;
> +
> +	/* enable interrupt before send */
> +	if (mbox->intr_mode)
> +		xilinx_mbox_tx_intmask(mbox, true);
> +
> +	writel_relaxed(*udata, mbox->mbox_base + MAILBOX_REG_WRDATA);
> +
> +	return 0;
> +}
> +
> +static bool xilinx_mbox_last_tx_done(struct mbox_chan *chan)
> +{
> +	struct xilinx_mbox *mbox = mbox_chan_to_xilinx_mbox(chan);
> +
> +	/* return false if mailbox is full */
> +	return xilinx_mbox_full(mbox) ? false : true;
> +}
> +
> +static bool xilinx_mbox_peek_data(struct mbox_chan *chan)
> +{
> +	struct xilinx_mbox *mbox = mbox_chan_to_xilinx_mbox(chan);
> +
> +	return xilinx_mbox_pending(mbox) ? true : false;
> +}
> +
> +static void xilinx_mbox_shutdown(struct mbox_chan *chan)
> +{
> +	struct xilinx_mbox *mbox = mbox_chan_to_xilinx_mbox(chan);
> +
> +	if (mbox->intr_mode) {
> +		/* unmask all interrupt masks */
> +		writel_relaxed(~0, mbox->mbox_base + MAILBOX_REG_IE);
> +		free_irq(mbox->irq, chan);
> +	} else
> +		del_timer_sync(&mbox->rxpoll_timer);

Also {} around else part.

> +}
> +
> +static struct mbox_chan_ops xilinx_mbox_ops = {
> +	.send_data = xilinx_mbox_send_data,
> +	.startup = xilinx_mbox_startup,
> +	.shutdown = xilinx_mbox_shutdown,
> +	.last_tx_done = xilinx_mbox_last_tx_done,
> +	.peek_data = xilinx_mbox_peek_data,
> +};
> +
> +static int xilinx_mbox_probe(struct platform_device *pdev)
> +{
> +	struct xilinx_mbox *mbox;
> +	struct resource	*regs;
> +	struct mbox_chan *chans;
> +	int ret;
> +
> +	mbox = devm_kzalloc(&pdev->dev, sizeof(*mbox),
> +			    GFP_KERNEL);

it should fit to one line - no reason for this indentation.

> +	if (!mbox)
> +		return -ENOMEM;
> +
> +	/* allocated one channel */
> +	chans = devm_kzalloc(&pdev->dev, sizeof(*chans), GFP_KERNEL);
> +	if (!chans)
> +		return -ENOMEM;
> +
> +	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +
> +	mbox->mbox_base = devm_ioremap_resource(&pdev->dev, regs);
> +	if (IS_ERR(mbox->mbox_base))
> +		return PTR_ERR(mbox->mbox_base);
> +
> +	mbox->irq = platform_get_irq(pdev, 0);
> +	/* if irq is present, we can use it, otherwise, poll */
> +	if (mbox->irq >= 0)
> +		mbox->intr_mode = true;
> +	else
> +		dev_info(&pdev->dev, "IRQ not found, fallback to polling.\n");

Is mbox->intr_mode needed at all?
You can simple detect it from mbox->irq anytime.


> +
> +	mbox->dev = &pdev->dev;
> +
> +	/* Hardware supports only one channel. */
> +	chans[0].con_priv = mbox;
> +	mbox->controller.dev = mbox->dev;
> +	mbox->controller.num_chans = 1;
> +	mbox->controller.chans = chans;
> +	mbox->controller.ops = &xilinx_mbox_ops;
> +
> +	if (mbox->intr_mode) {
> +		mbox->controller.txdone_irq = true;
> +	} else {
> +		mbox->controller.txdone_poll = true;
> +		mbox->controller.txpoll_period = MBOX_POLLING_MS;
> +	}

why is this in the different block? Just put it together with above
error message.

> +
> +	ret = mbox_controller_register(&mbox->controller);
> +	if (ret) {
> +		dev_err(&pdev->dev, "Register mailbox failed\n");
> +		goto err;

Just return ret here

> +	}
> +
> +	platform_set_drvdata(pdev, mbox);
> +err:
> +	return ret;

return 0;

> +}
> +
> +
> +static int xilinx_mbox_remove(struct platform_device *pdev)
> +{
> +	struct xilinx_mbox *mbox = platform_get_drvdata(pdev);
> +
> +	if (!mbox)
> +		return -EINVAL;
> +
> +	mbox_controller_unregister(&mbox->controller);
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id xilinx_mbox_match[] = {
> +	{ .compatible = "xlnx,mailbox-2.1" },
> +	{ /* Sentinel */ }
> +};
> +
> +MODULE_DEVICE_TABLE(of, xilinx_mbox_match);
> +
> +static struct platform_driver xilinx_mbox_driver = {
> +	.probe	= xilinx_mbox_probe,
> +	.remove	= xilinx_mbox_remove,
> +	.driver	= {
> +		.name	= DRIVER_NAME,
> +		.of_match_table	= xilinx_mbox_match,
> +	},
> +};
> +
> +module_platform_driver(xilinx_mbox_driver);
> +
> +MODULE_LICENSE("GPL v2");
> +MODULE_DESCRIPTION("Xilinx mailbox specific functions");
> +MODULE_AUTHOR("Moritz Fischer <moritz.fischer@ettus.com>");
> +MODULE_ALIAS("platform:xilinx-mailbox");

This is fine but have you tested it as a plain platform driver?

Thanks,
Michal

WARNING: multiple messages have this Message-ID (diff)
From: Michal Simek <michal.simek@xilinx.com>
To: Moritz Fischer <moritz.fischer@ettus.com>, <jassisinghbrar@gmail.com>
Cc: <linux-kernel@vger.kernel.org>, <robh+dt@kernel.org>,
	<pawel.moll@arm.com>, <mark.rutland@arm.com>,
	<ijc+devicetree@hellion.org.uk>, <galak@codeaurora.org>,
	<michal.simek@xilinx.com>, <soren.brinkmann@xilinx.com>,
	<akpm@linux-foundation.org>, <gregkh@linuxfoundation.org>,
	<mchehab@osg.samsung.com>, <arnd@arndb.de>, <joe@perches.com>,
	<jingoohan1@gmail.com>, <devicetree@vger.kernel.org>,
	<linux-arm-kernel@lists.infradead.org>
Subject: Re: [PATCH 1/3] mailbox: Adding driver for Xilinx LogiCORE IP mailbox.
Date: Fri, 22 May 2015 09:08:06 +0200	[thread overview]
Message-ID: <555ED5D6.2080600@xilinx.com> (raw)
In-Reply-To: <1432251450-26352-2-git-send-email-moritz.fischer@ettus.com>

On 05/22/2015 01:37 AM, Moritz Fischer wrote:
> The Xilinx LogiCORE IP mailbox is a FPGA core that allows for
> interprocessor communication via AXI4 memory mapped / AXI4 stream
> interfaces.
> 
> It is single channel per core and allows for transmit and receive.
> 
> Signed-off-by: Moritz Fischer <moritz.fischer@ettus.com>
> ---
>  drivers/mailbox/Kconfig          |   8 +
>  drivers/mailbox/Makefile         |   2 +
>  drivers/mailbox/mailbox-xilinx.c | 339 ++++++++++++++++++++++++++++++++++
>  3 files changed, 349 insertions(+)
> 
> diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
> index 84b0a2d..e11e4b2 100644
> --- a/drivers/mailbox/Kconfig
> +++ b/drivers/mailbox/Kconfig
> @@ -60,4 +60,12 @@ config ALTERA_MBOX
>  	  An implementation of the Altera Mailbox soft core. It is used
>  	  to send message between processors. Say Y here if you want to use the
>  	  Altera mailbox support.
> +
> +config XILINX_MBOX
> +	tristate "Xilinx Mailbox"
> +	help
> +	  An implementation of the Xilinx Mailbox soft core. It is used
> +	  to send message between processors. Say Y here if you want to use the
> +	  Xilinx mailbox support.
> +
>  endif
> diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
> index b18201e..d28a028 100644
> --- a/drivers/mailbox/Makefile
> +++ b/drivers/mailbox/Makefile
> @@ -11,3 +11,5 @@ obj-$(CONFIG_OMAP2PLUS_MBOX)	+= omap-mailbox.o
>  obj-$(CONFIG_PCC)		+= pcc.o
>  
>  obj-$(CONFIG_ALTERA_MBOX)	+= mailbox-altera.o
> +
> +obj-$(CONFIG_XILINX_MBOX)	+= mailbox-xilinx.o
> diff --git a/drivers/mailbox/mailbox-xilinx.c b/drivers/mailbox/mailbox-xilinx.c
> new file mode 100644
> index 0000000..8d8aa17
> --- /dev/null
> +++ b/drivers/mailbox/mailbox-xilinx.c
> @@ -0,0 +1,339 @@
> +/*
> + * Copyright (c) 2015, National Instruments Corp. All rights reserved.
> + *
> + * Driver for the Xilinx Logicore mailbox IP block
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; version 2 of the License.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + */
> +
> +#include <linux/device.h>
> +#include <linux/interrupt.h>
> +#include <linux/io.h>
> +#include <linux/kernel.h>
> +#include <linux/mailbox_controller.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/platform_device.h>
> +
> +#define DRIVER_NAME "xilinx-mailbox"
> +
> +/* register offsets */
> +#define MAILBOX_REG_WRDATA 0x00

I prefer to use #define<space>macro_name<tab>value
but up to you.

> +#define MAILBOX_REG_RDDATA 0x08
> +#define MAILBOX_REG_STATUS 0x10
> +#define MAILBOX_REG_ERROR 0x14
> +#define MAILBOX_REG_SIT 0x18
> +#define MAILBOX_REG_RIT 0x1c
> +#define MAILBOX_REG_IS 0x20
> +#define MAILBOX_REG_IE 0x24
> +#define MAILBOX_REG_IP 0x28
> +
> +/* status register */
> +#define STS_RTA BIT(3)
> +#define STS_STA BIT(2)
> +#define STS_FULL BIT(1)
> +#define STS_EMPTY BIT(0)
> +
> +/* error register */
> +#define ERR_FULL BIT(1)
> +#define ERR_EMPTY BIT(0)
> +
> +/* mailbox interrupt status register */
> +#define INT_STATUS_ERR BIT(2)
> +#define INT_STATUS_RTI BIT(1)
> +#define INT_STATUS_STI BIT(0)
> +
> +/* mailbox interrupt enable register */
> +#define INT_ENABLE_ERR BIT(2)
> +#define INT_ENABLE_RTI BIT(1)
> +#define INT_ENABLE_STI BIT(0)
> +
> +#define MBOX_POLLING_MS		5	/* polling interval 5ms */

and you are using tab here - it looks like c&p from somewhere. :-)

> +
> +struct xilinx_mbox {
> +	bool intr_mode;

look below.

> +	int irq;
> +	void __iomem *mbox_base;
> +	struct device *dev;
> +	struct mbox_controller controller;
> +
> +	/* if the controller supports only RX polling mode */
> +	struct timer_list rxpoll_timer;
> +};
> +
> +static struct xilinx_mbox *mbox_chan_to_xilinx_mbox(struct mbox_chan *chan)
> +{
> +	if (!chan || !chan->con_priv)
> +		return NULL;
> +
> +	return (struct xilinx_mbox *)chan->con_priv;
> +}
> +
> +static inline int xilinx_mbox_full(struct xilinx_mbox *mbox)
> +{
> +	u32 status;
> +
> +	status = readl_relaxed(mbox->mbox_base + MAILBOX_REG_STATUS);

empty line here please for easier reading.

> +	return status & STS_FULL;
> +}
> +
> +static inline int xilinx_mbox_pending(struct xilinx_mbox *mbox)
> +{
> +	u32 status;
> +
> +	status = readl_relaxed(mbox->mbox_base + MAILBOX_REG_STATUS);

ditto.

> +	return !(status & STS_EMPTY);
> +}
> +
> +static void xilinx_mbox_rx_intmask(struct xilinx_mbox *mbox, bool enable)
> +{
> +	u32 mask;
> +
> +	mask = readl_relaxed(mbox->mbox_base + MAILBOX_REG_IE);
> +	if (enable)
> +		mask |= INT_ENABLE_RTI;
> +	else
> +		mask &= ~INT_ENABLE_RTI;
> +	writel_relaxed(mask, mbox->mbox_base + MAILBOX_REG_IE);
> +}
> +
> +static void xilinx_mbox_tx_intmask(struct xilinx_mbox *mbox, bool enable)
> +{
> +	u32 mask;
> +
> +	mask = readl_relaxed(mbox->mbox_base + MAILBOX_REG_IE);
> +	if (enable)
> +		mask |= INT_ENABLE_STI;
> +	else
> +		mask &= ~INT_ENABLE_STI;
> +	writel_relaxed(mask, mbox->mbox_base + MAILBOX_REG_IE);
> +}
> +
> +static void xilinx_mbox_rx_data(struct mbox_chan *chan)
> +{
> +	struct xilinx_mbox *mbox = mbox_chan_to_xilinx_mbox(chan);
> +	u32 data;
> +
> +	if (xilinx_mbox_pending(mbox)) {
> +		data = readl_relaxed(mbox->mbox_base + MAILBOX_REG_RDDATA);
> +		mbox_chan_received_data(chan, (void *)data);
> +	}
> +}
> +
> +static void xilinx_mbox_poll_rx(unsigned long data)
> +{
> +	struct mbox_chan *chan = (struct mbox_chan *)data;
> +	struct xilinx_mbox *mbox = mbox_chan_to_xilinx_mbox(chan);
> +
> +	xilinx_mbox_rx_data(chan);
> +
> +	mod_timer(&mbox->rxpoll_timer,
> +		  jiffies + msecs_to_jiffies(MBOX_POLLING_MS));
> +}
> +
> +static irqreturn_t xilinx_mbox_interrupt(int irq, void *p)
> +{
> +	u32 mask;
> +	struct mbox_chan *chan = (struct mbox_chan *)p;
> +	struct xilinx_mbox *mbox = mbox_chan_to_xilinx_mbox(chan);
> +
> +	mask = readl_relaxed(mbox->mbox_base + MAILBOX_REG_IS);
> +	if (mask & INT_STATUS_RTI)
> +		xilinx_mbox_rx_data(chan);
> +
> +	/* mask irqs *before* notifying done, require tx_block=true */
> +	if (mask & INT_STATUS_STI) {
> +		xilinx_mbox_tx_intmask(mbox, false);
> +		mbox_chan_txdone(chan, 0);
> +	}
> +
> +	if (mask & INT_STATUS_ERR)
> +		dev_err(mbox->dev, "Got error IRQ!\n");
> +
> +	writel_relaxed(mask, mbox->mbox_base + MAILBOX_REG_IS);

one more empty line here.

> +	return IRQ_HANDLED;
> +}
> +
> +static int xilinx_mbox_startup(struct mbox_chan *chan)
> +{
> +	int ret;
> +	struct xilinx_mbox *mbox = mbox_chan_to_xilinx_mbox(chan);
> +
> +	if (mbox->intr_mode) {

look below

> +		ret = request_irq(mbox->irq, xilinx_mbox_interrupt, 0,
> +				  dev_name(mbox->dev), chan);
> +		if (unlikely(ret)) {
> +			dev_err(mbox->dev,
> +				"failed to register mailbox interrupt:%d\n",
> +				ret);
> +			mbox->intr_mode = false;
> +			goto polling; /* use polling if failed */
> +		}
> +
> +		xilinx_mbox_rx_intmask(mbox, true);

Are you also setting up polling timer for interrupt mode?
Or here should be return?

> +	}
> +
> +polling:
> +	/* setup polling timer */
> +	setup_timer(&mbox->rxpoll_timer, xilinx_mbox_poll_rx,
> +		    (unsigned long)chan);
> +	mod_timer(&mbox->rxpoll_timer,
> +		  jiffies + msecs_to_jiffies(MBOX_POLLING_MS));
> +
> +	return 0;
> +}
> +
> +static int xilinx_mbox_send_data(struct mbox_chan *chan, void *data)
> +{
> +	struct xilinx_mbox *mbox = mbox_chan_to_xilinx_mbox(chan);
> +	u32 *udata = (u32 *)data;
> +
> +	if (!mbox || !data)
> +		return -EINVAL;
> +
> +	if (xilinx_mbox_full(mbox))
> +		return -EBUSY;
> +
> +	/* enable interrupt before send */
> +	if (mbox->intr_mode)
> +		xilinx_mbox_tx_intmask(mbox, true);
> +
> +	writel_relaxed(*udata, mbox->mbox_base + MAILBOX_REG_WRDATA);
> +
> +	return 0;
> +}
> +
> +static bool xilinx_mbox_last_tx_done(struct mbox_chan *chan)
> +{
> +	struct xilinx_mbox *mbox = mbox_chan_to_xilinx_mbox(chan);
> +
> +	/* return false if mailbox is full */
> +	return xilinx_mbox_full(mbox) ? false : true;
> +}
> +
> +static bool xilinx_mbox_peek_data(struct mbox_chan *chan)
> +{
> +	struct xilinx_mbox *mbox = mbox_chan_to_xilinx_mbox(chan);
> +
> +	return xilinx_mbox_pending(mbox) ? true : false;
> +}
> +
> +static void xilinx_mbox_shutdown(struct mbox_chan *chan)
> +{
> +	struct xilinx_mbox *mbox = mbox_chan_to_xilinx_mbox(chan);
> +
> +	if (mbox->intr_mode) {
> +		/* unmask all interrupt masks */
> +		writel_relaxed(~0, mbox->mbox_base + MAILBOX_REG_IE);
> +		free_irq(mbox->irq, chan);
> +	} else
> +		del_timer_sync(&mbox->rxpoll_timer);

Also {} around else part.

> +}
> +
> +static struct mbox_chan_ops xilinx_mbox_ops = {
> +	.send_data = xilinx_mbox_send_data,
> +	.startup = xilinx_mbox_startup,
> +	.shutdown = xilinx_mbox_shutdown,
> +	.last_tx_done = xilinx_mbox_last_tx_done,
> +	.peek_data = xilinx_mbox_peek_data,
> +};
> +
> +static int xilinx_mbox_probe(struct platform_device *pdev)
> +{
> +	struct xilinx_mbox *mbox;
> +	struct resource	*regs;
> +	struct mbox_chan *chans;
> +	int ret;
> +
> +	mbox = devm_kzalloc(&pdev->dev, sizeof(*mbox),
> +			    GFP_KERNEL);

it should fit to one line - no reason for this indentation.

> +	if (!mbox)
> +		return -ENOMEM;
> +
> +	/* allocated one channel */
> +	chans = devm_kzalloc(&pdev->dev, sizeof(*chans), GFP_KERNEL);
> +	if (!chans)
> +		return -ENOMEM;
> +
> +	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
> +
> +	mbox->mbox_base = devm_ioremap_resource(&pdev->dev, regs);
> +	if (IS_ERR(mbox->mbox_base))
> +		return PTR_ERR(mbox->mbox_base);
> +
> +	mbox->irq = platform_get_irq(pdev, 0);
> +	/* if irq is present, we can use it, otherwise, poll */
> +	if (mbox->irq >= 0)
> +		mbox->intr_mode = true;
> +	else
> +		dev_info(&pdev->dev, "IRQ not found, fallback to polling.\n");

Is mbox->intr_mode needed at all?
You can simple detect it from mbox->irq anytime.


> +
> +	mbox->dev = &pdev->dev;
> +
> +	/* Hardware supports only one channel. */
> +	chans[0].con_priv = mbox;
> +	mbox->controller.dev = mbox->dev;
> +	mbox->controller.num_chans = 1;
> +	mbox->controller.chans = chans;
> +	mbox->controller.ops = &xilinx_mbox_ops;
> +
> +	if (mbox->intr_mode) {
> +		mbox->controller.txdone_irq = true;
> +	} else {
> +		mbox->controller.txdone_poll = true;
> +		mbox->controller.txpoll_period = MBOX_POLLING_MS;
> +	}

why is this in the different block? Just put it together with above
error message.

> +
> +	ret = mbox_controller_register(&mbox->controller);
> +	if (ret) {
> +		dev_err(&pdev->dev, "Register mailbox failed\n");
> +		goto err;

Just return ret here

> +	}
> +
> +	platform_set_drvdata(pdev, mbox);
> +err:
> +	return ret;

return 0;

> +}
> +
> +
> +static int xilinx_mbox_remove(struct platform_device *pdev)
> +{
> +	struct xilinx_mbox *mbox = platform_get_drvdata(pdev);
> +
> +	if (!mbox)
> +		return -EINVAL;
> +
> +	mbox_controller_unregister(&mbox->controller);
> +
> +	return 0;
> +}
> +
> +static const struct of_device_id xilinx_mbox_match[] = {
> +	{ .compatible = "xlnx,mailbox-2.1" },
> +	{ /* Sentinel */ }
> +};
> +
> +MODULE_DEVICE_TABLE(of, xilinx_mbox_match);
> +
> +static struct platform_driver xilinx_mbox_driver = {
> +	.probe	= xilinx_mbox_probe,
> +	.remove	= xilinx_mbox_remove,
> +	.driver	= {
> +		.name	= DRIVER_NAME,
> +		.of_match_table	= xilinx_mbox_match,
> +	},
> +};
> +
> +module_platform_driver(xilinx_mbox_driver);
> +
> +MODULE_LICENSE("GPL v2");
> +MODULE_DESCRIPTION("Xilinx mailbox specific functions");
> +MODULE_AUTHOR("Moritz Fischer <moritz.fischer@ettus.com>");
> +MODULE_ALIAS("platform:xilinx-mailbox");

This is fine but have you tested it as a plain platform driver?

Thanks,
Michal




  parent reply	other threads:[~2015-05-22  7:08 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-05-21 23:37 [PATCH 0/3] Adding driver for Xilinx LogiCORE IP mailbox Moritz Fischer
2015-05-21 23:37 ` Moritz Fischer
2015-05-21 23:37 ` [PATCH 1/3] mailbox: " Moritz Fischer
2015-05-21 23:37   ` Moritz Fischer
2015-05-21 23:37   ` Moritz Fischer
2015-05-22  6:32   ` Shubhrajyoti Datta
2015-05-22  6:32     ` Shubhrajyoti Datta
2015-05-22  6:32     ` Shubhrajyoti Datta
2015-05-22  7:08   ` Michal Simek [this message]
2015-05-22  7:08     ` Michal Simek
2015-05-22  7:08     ` Michal Simek
2015-05-21 23:37 ` [PATCH 2/3] dts: Adding docs for Xilinx LogiCORE IP mailbox driver Moritz Fischer
2015-05-21 23:37   ` Moritz Fischer
2015-05-21 23:37   ` Moritz Fischer
2015-05-22  5:43   ` Michal Simek
2015-05-22  5:43     ` Michal Simek
2015-05-22  5:43     ` Michal Simek
2015-05-25 19:04     ` Sören Brinkmann
2015-05-25 19:04       ` Sören Brinkmann
2015-05-25 19:04       ` Sören Brinkmann
2015-05-26 16:15       ` Moritz Fischer
2015-05-26 16:15         ` Moritz Fischer
2015-05-21 23:37 ` [PATCH 3/3] MAINTAINERS: Add entry for xilinx " Moritz Fischer
2015-05-21 23:37   ` Moritz Fischer
2015-05-21 23:37   ` Moritz Fischer
2015-05-22  5:44   ` Michal Simek
2015-05-22  5:44     ` Michal Simek
2015-05-22  5:44     ` Michal Simek

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=555ED5D6.2080600@xilinx.com \
    --to=michal.simek@xilinx.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.