diff mbox

[v7,2/7] mailbox: arm_mhu: add driver for ARM MHU controller

Message ID 1425466884-30648-1-git-send-email-vincent.yang@socionext.com
State Accepted, archived
Commit ee23d66af9219dfe2407a9b08ef9a165dbe6f994
Headers show

Commit Message

Vincent Yang March 4, 2015, 11:01 a.m. UTC
From: Jassi Brar <jaswinder.singh@linaro.org>

Add driver for the ARM Primecell Message-Handling-Unit(MHU) controller.

Signed-off-by: Jassi Brar <jaswinder.singh@linaro.org>
Signed-off-by: Andy Green <andy.green@linaro.org>
Signed-off-by: Vincent Yang <vincent.yang@socionext.com>
Signed-off-by: Tetsuya Nuriya <nuriya.tetsuya@socionext.com>
---
 .../devicetree/bindings/mailbox/arm-mhu.txt        |  43 +++++
 drivers/mailbox/Kconfig                            |   9 +
 drivers/mailbox/Makefile                           |   2 +
 drivers/mailbox/arm_mhu.c                          | 195 +++++++++++++++++++++
 4 files changed, 249 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/mailbox/arm-mhu.txt
 create mode 100644 drivers/mailbox/arm_mhu.c

Comments

Sudeep Holla March 18, 2015, 9:57 a.m. UTC | #1
Hi Vincent,

I see that this driver is queued but most of my earlier comments were
not addressed. *No ACK from DT binding maintainers too*.

On 04/03/15 11:01, Vincent Yang wrote:
> From: Jassi Brar <jaswinder.singh@linaro.org>
>
> Add driver for the ARM Primecell Message-Handling-Unit(MHU) controller.
>
> Signed-off-by: Jassi Brar <jaswinder.singh@linaro.org>
> Signed-off-by: Andy Green <andy.green@linaro.org>
> Signed-off-by: Vincent Yang <vincent.yang@socionext.com>
> Signed-off-by: Tetsuya Nuriya <nuriya.tetsuya@socionext.com>
> ---
>   .../devicetree/bindings/mailbox/arm-mhu.txt        |  43 +++++
>   drivers/mailbox/Kconfig                            |   9 +
>   drivers/mailbox/Makefile                           |   2 +
>   drivers/mailbox/arm_mhu.c                          | 195 +++++++++++++++++++++
>   4 files changed, 249 insertions(+)
>   create mode 100644 Documentation/devicetree/bindings/mailbox/arm-mhu.txt
>   create mode 100644 drivers/mailbox/arm_mhu.c
>
> diff --git a/Documentation/devicetree/bindings/mailbox/arm-mhu.txt b/Documentation/devicetree/bindings/mailbox/arm-mhu.txt
> new file mode 100644
> index 0000000..4971f03
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mailbox/arm-mhu.txt
> @@ -0,0 +1,43 @@
> +ARM MHU Mailbox Driver
> +======================
> +
> +The ARM's Message-Handling-Unit (MHU) is a mailbox controller that has
> +3 independent channels/links to communicate with remote processor(s).
> + MHU links are hardwired on a platform. A link raises interrupt for any

As I had mentioned before it's just one implementation, the IP had
provision bi-directional interrupts and the binding *has to consider*
that instead of having to workaround that later.

> +received data. However, there is no specified way of knowing if the sent

You can drop the above line or specify as you can still poll.

> +data has been read by the remote. This driver assumes the sender polls

Bindings not supposed have any details on how driver handle it. You can
just mention that in absence of interrupt, we can know the status of
transmission by polling STAT register.

> +STAT register and the remote clears it after having read the data.
> +The last channel is specified to be a 'Secure' resource, hence can't be
> +used by Linux running NS.
> +

Correct so drop the support for secure channel until the first user
comes up. I am worried it might generate abort if someone tries to
access it in ARM64 which always runs in non-secure.


> +Mailbox Device Node:
> +====================
> +
> +Required properties:
> +--------------------
> +- compatible:		Shall be "arm,mhu" & "arm,primecell"
> +- reg:			Contains the mailbox register address range (base
> +			address and length)
> +- #mbox-cells		Shall be 1 - the index of the channel needed.
> +- interrupts:		Contains the interrupt information corresponding to
> +			each of the 3 links of MHU.
> +

As mentioned multiple times before, please add interrupt-names to make
sure we can handle bi-directional interrupt.

> +Example:
> +--------
> +
> +	mhu: mailbox@2b1f0000 {
> +		#mbox-cells = <1>;
> +		compatible = "arm,mhu", "arm,primecell";
> +		reg = <0 0x2b1f0000 0x1000>;
> +		interrupts = <0 36 4>, /* LP-NonSecure */
> +			     <0 35 4>, /* HP-NonSecure */
> +			     <0 37 4>; /* Secure */
> +		clocks = <&clock 0 2 1>;
> +		clock-names = "apb_pclk";
> +	};
> +
> +	mhu_client: scb@2e000000 {
> +		compatible = "fujitsu,mb86s70-scb-1.0";
> +		reg = <0 0x2e000000 0x4000>;
> +		mboxes = <&mhu 1>; /* HP-NonSecure */
> +	};

[...]

> diff --git a/drivers/mailbox/arm_mhu.c b/drivers/mailbox/arm_mhu.c
> new file mode 100644
> index 0000000..ac693c6
> --- /dev/null
> +++ b/drivers/mailbox/arm_mhu.c
> @@ -0,0 +1,195 @@
> +/*
> + * Copyright (C) 2013-2015 Fujitsu Semiconductor Ltd.
> + * Copyright (C) 2015 Linaro Ltd.
> + * Author: Jassi Brar <jaswinder.singh@linaro.org>
> + *
> + * 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/interrupt.h>
> +#include <linux/spinlock.h>
> +#include <linux/mutex.h>
> +#include <linux/delay.h>
> +#include <linux/slab.h>
> +#include <linux/err.h>
> +#include <linux/io.h>
> +#include <linux/module.h>
> +#include <linux/amba/bus.h>
> +#include <linux/mailbox_controller.h>
> +
> +#define INTR_STAT_OFS	0x0
> +#define INTR_SET_OFS	0x8
> +#define INTR_CLR_OFS	0x10
> +
> +#define MHU_LP_OFFSET	0x0
> +#define MHU_HP_OFFSET	0x20
> +#define MHU_SEC_OFFSET	0x200
> +#define TX_REG_OFFSET	0x100
> +
> +#define MHU_CHANS	3
> +

For now I prefer 2.

[...]
> +static int mhu_probe(struct amba_device *adev, const struct amba_id *id)
> +{
> +	int i, err;
> +	struct arm_mhu *mhu;
> +	struct device *dev = &adev->dev;
> +	int mhu_reg[MHU_CHANS] = {MHU_LP_OFFSET, MHU_HP_OFFSET, MHU_SEC_OFFSET};
> +
> +	/* Allocate memory for device */
> +	mhu = devm_kzalloc(dev, sizeof(*mhu), GFP_KERNEL);
> +	if (!mhu)
> +		return -ENOMEM;
> +
> +	mhu->base = devm_ioremap_resource(dev, &adev->res);
> +	if (IS_ERR(mhu->base)) {
> +		dev_err(dev, "ioremap failed\n");
> +		return PTR_ERR(mhu->base);
> +	}
> +
> +	for (i = 0; i < MHU_CHANS; i++) {
> +		mhu->chan[i].con_priv = &mhu->mlink[i];
> +		mhu->mlink[i].irq = adev->irq[i];
> +		mhu->mlink[i].rx_reg = mhu->base + mhu_reg[i];
> +		mhu->mlink[i].tx_reg = mhu->mlink[i].rx_reg + TX_REG_OFFSET;
> +	}
> +
> +	mhu->mbox.dev = dev;
> +	mhu->mbox.chans = &mhu->chan[0];
> +	mhu->mbox.num_chans = MHU_CHANS;
> +	mhu->mbox.ops = &mhu_ops;
> +	mhu->mbox.txdone_irq = false;
> +	mhu->mbox.txdone_poll = true;
> +	mhu->mbox.txpoll_period = 10;

IMO too high value, as I mentioned you assume jiffy value. The kernel
will take care of conversion.

[...]
> +
> +static struct amba_id mhu_ids[] = {
> +	{
> +		.id	= 0x1bb098,

As I mentioned couple of times this is broken. Please refer my earlier 
mail for details. You are skipping a field to compare which incorrect.
You are just trying to get it working with existing AMBA driver without 
any changes matching the IDs partially.

Regards,
Sudeep

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sudeep Holla March 18, 2015, 10:25 a.m. UTC | #2
Hi Vincent,

Forgot couple of things earlier:

On 04/03/15 11:01, Vincent Yang wrote:
> From: Jassi Brar <jaswinder.singh@linaro.org>
>
> Add driver for the ARM Primecell Message-Handling-Unit(MHU) controller.
>
> Signed-off-by: Jassi Brar <jaswinder.singh@linaro.org>
> Signed-off-by: Andy Green <andy.green@linaro.org>
> Signed-off-by: Vincent Yang <vincent.yang@socionext.com>
> Signed-off-by: Tetsuya Nuriya <nuriya.tetsuya@socionext.com>
> ---
>   .../devicetree/bindings/mailbox/arm-mhu.txt        |  43 +++++
>   drivers/mailbox/Kconfig                            |   9 +
>   drivers/mailbox/Makefile                           |   2 +
>   drivers/mailbox/arm_mhu.c                          | 195 +++++++++++++++++++++
>   4 files changed, 249 insertions(+)
>   create mode 100644 Documentation/devicetree/bindings/mailbox/arm-mhu.txt
>   create mode 100644 drivers/mailbox/arm_mhu.c
>

[...]

> +static int mhu_send_data(struct mbox_chan *chan, void *data)
> +{
> +	struct mhu_link *mlink = chan->con_priv;
> +	u32 *arg = data;
> +

Arnd doesn't like this and had suggestions in some other thread.

> +	writel_relaxed(*arg, mlink->tx_reg + INTR_SET_OFS);
> +
> +	return 0;
> +}
> +
> +static int mhu_startup(struct mbox_chan *chan)
> +{
> +	struct mhu_link *mlink = chan->con_priv;
> +	u32 val;
> +	int ret;
> +
> +	val = readl_relaxed(mlink->tx_reg + INTR_STAT_OFS);
> +	writel_relaxed(val, mlink->tx_reg + INTR_CLR_OFS);
> +
> +	ret = request_irq(mlink->irq, mhu_rx_interrupt,
> +			  IRQF_SHARED, "mhu_link", chan);

Any reason we can't move this to probe and have {en,dis}able_irq here if
needed. I has seen it was too heavy to have these especially when
sending small packets.

Regards,
Sudeep

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Jassi Brar March 18, 2015, 12:56 p.m. UTC | #3
On Wed, Mar 18, 2015 at 3:27 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
> Hi Vincent,
>
> I see that this driver is queued but most of my earlier comments were
> not addressed.
>
Some of your comments have been addressed as changes and some as replies.

> *No ACK from DT binding maintainers too*.
>
Yeah it would have been great to have some ack. It has been many
months now, but I see its not uncommon for bindings go in via
maintainers. I assume folks find it just normal.


>> +++ b/Documentation/devicetree/bindings/mailbox/arm-mhu.txt
>> @@ -0,0 +1,43 @@
>> +ARM MHU Mailbox Driver
>> +======================
>> +
>> +The ARM's Message-Handling-Unit (MHU) is a mailbox controller that has
>> +3 independent channels/links to communicate with remote processor(s).
>> + MHU links are hardwired on a platform. A link raises interrupt for any
>
>
> As I had mentioned before it's just one implementation, the IP had
> provision bi-directional interrupts and the binding *has to consider*
> that instead of having to workaround that later.
>
I will reply in yet another way.... the spec I have don't mention that
(and it makes sense) and your platform doesn't do that either. I would
have had to do something about it, had there been such a weird setup,
but there's none known.

 So let us please avoid getting into bikeshedding discussion yet
again. Otherwise almost every binding is broken because there could
always be some platform that does weird things with irqs.

>> +The last channel is specified to be a 'Secure' resource, hence can't be
>> +used by Linux running NS.
>
> Correct so drop the support for secure channel until the first user
> comes up.
>
In your last post you said:
  "Sorry my statement was not clear, I wanted to ask you to add that info
to the binding."
  Not that it makes sense to say the obvious, I added it just to
address your comment.

> I am worried it might generate abort if someone tries to
> access it in ARM64 which always runs in non-secure.
>
Abort should have happened years ago if someone _tries_ to access a
secure resource from non-secure mode ;)
How do you protect such people from "trying to" dereference NULL
pointers?  (you made me repeat Nth time).

>> +
>> +static struct amba_id mhu_ids[] = {
>> +       {
>> +               .id     = 0x1bb098,
>
>
> As I mentioned couple of times this is broken. Please refer my earlier mail
> for details. You are skipping a field to compare which incorrect.
> You are just trying to get it working with existing AMBA driver without any
> changes matching the IDs partially.
>
I did not miss your last mail. Let me try to reply in even simpler
terms... PID[0,3] identification is fine grained enough. If/when we
have some platform with non-ARM MHU, we could catch that in this
driver. Most likely even then the reg-map won't change drastically, if
at all. So we could ignore the PID4, otherwise we check PID4 in this
driver and adapt the behavior.

-Jassi
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Jassi Brar March 18, 2015, 1:19 p.m. UTC | #4
On Wed, Mar 18, 2015 at 3:55 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>
>> +static int mhu_send_data(struct mbox_chan *chan, void *data)
>> +{
>> +       struct mhu_link *mlink = chan->con_priv;
>> +       u32 *arg = data;
>
> Arnd doesn't like this and had suggestions in some other thread.
>
No, Arnd suggested doing it this way. And another platform's driver
was made to do this way.

>> +       writel_relaxed(*arg, mlink->tx_reg + INTR_SET_OFS);
>> +
>> +       return 0;
>> +}
>> +
>> +static int mhu_startup(struct mbox_chan *chan)
>> +{
>> +       struct mhu_link *mlink = chan->con_priv;
>> +       u32 val;
>> +       int ret;
>> +
>> +       val = readl_relaxed(mlink->tx_reg + INTR_STAT_OFS);
>> +       writel_relaxed(val, mlink->tx_reg + INTR_CLR_OFS);
>> +
>> +       ret = request_irq(mlink->irq, mhu_rx_interrupt,
>> +                         IRQF_SHARED, "mhu_link", chan);
>
>
> Any reason we can't move this to probe and have {en,dis}able_irq here if
> needed. I has seen it was too heavy to have these especially when
> sending small packets.
>
I see you used to do memcpy in irq-handler
https://git.linaro.org/landing-teams/working/arm/kernel.git/blob/HEAD:/drivers/mailbox/arm_mhu.c
perhaps you were using your old driver?

If you use this new driver, and send packets so often that
request-release irq has effect, maybe should hold the mailbox
reference for lifetime. I remember suggesting you that already and I
remember you said that's how it was.

-Jassi
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sudeep Holla March 18, 2015, 2:08 p.m. UTC | #5
On 18/03/15 12:56, Jassi Brar wrote:
> On Wed, Mar 18, 2015 at 3:27 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>> Hi Vincent,
>>
>> I see that this driver is queued but most of my earlier comments were
>> not addressed.
>>
> Some of your comments have been addressed as changes and some as replies.
>
>> *No ACK from DT binding maintainers too*.
>>
> Yeah it would have been great to have some ack. It has been many
> months now, but I see its not uncommon for bindings go in via
> maintainers. I assume folks find it just normal.
>

OK, but I have one concern in the binding as mentioned previous and
again as below.

>>> +++ b/Documentation/devicetree/bindings/mailbox/arm-mhu.txt
>>> @@ -0,0 +1,43 @@
>>> +ARM MHU Mailbox Driver
>>> +======================
>>> +
>>> +The ARM's Message-Handling-Unit (MHU) is a mailbox controller that has
>>> +3 independent channels/links to communicate with remote processor(s).
>>> + MHU links are hardwired on a platform. A link raises interrupt for any
>>
>>
>> As I had mentioned before it's just one implementation, the IP had
>> provision bi-directional interrupts and the binding *has to consider*
>> that instead of having to workaround that later.
>>
> I will reply in yet another way.... the spec I have don't mention that
> (and it makes sense) and your platform doesn't do that either. I would
> have had to do something about it, had there been such a weird setup,
> but there's none known.
>

Not just weird setup, even extending Tx support with this binding is not
straight forward.

Simple example:
Today you have:
		interrupts = <0 36 4>, /* LP-NonSecure */
			     <0 35 4>, /* HP-NonSecure */
			     <0 37 4>; /* Secure */

I don't want to specify Secure IRQ on my platform, which should be fine.
In future a variant of that platform gets Tx interrupts, then I will add
something like below:
		interrupts = <0 36 4>, /* LP-NonSecure Rx */
			     <0 35 4>, /* HP-NonSecure Rx */
			     <0 39 4>, /* LP-NonSecure Tx */
			     <0 38 4>, /* HP-NonSecure Tx */

Now how will we handle this ?

I am just suggesting to use interrupt-names so that we don't depend on
ordering in DT implicitly from first by fixing the binding.

>   So let us please avoid getting into bikeshedding discussion yet
> again. Otherwise almost every binding is broken because there could
> always be some platform that does weird things with irqs.
>

Sorry I don't buy that given that using interrupt-names simplifies
things and also helps to hand any such cases.

>>> +The last channel is specified to be a 'Secure' resource, hence can't be
>>> +used by Linux running NS.
>>
>> Correct so drop the support for secure channel until the first user
>> comes up.
>>
> In your last post you said:
>    "Sorry my statement was not clear, I wanted to ask you to add that info
> to the binding."
>    Not that it makes sense to say the obvious, I added it just to
> address your comment.
>
>> I am worried it might generate abort if someone tries to
>> access it in ARM64 which always runs in non-secure.
>>
> Abort should have happened years ago if someone _tries_ to access a
> secure resource from non-secure mode ;)
> How do you protect such people from "trying to" dereference NULL
> pointers?  (you made me repeat Nth time).
>

When the general practice everywhere in the kernel is to avoid secure
accesses *unless and until absolutely necessary*, I don't understand
*why exactly we need the exception here* ? I am OK if you add that
justification with the first user of that channel. We have seen several
cases/issues around that and I am just looking for a strong reason to
add secure channel support here.

>>> +
>>> +static struct amba_id mhu_ids[] = {
>>> +       {
>>> +               .id     = 0x1bb098,
>>
>>
>> As I mentioned couple of times this is broken. Please refer my earlier mail
>> for details. You are skipping a field to compare which incorrect.
>> You are just trying to get it working with existing AMBA driver without any
>> changes matching the IDs partially.
>>
> I did not miss your last mail. Let me try to reply in even simpler
> terms... PID[0,3] identification is fine grained enough. If/when we
> have some platform with non-ARM MHU, we could catch that in this
> driver. Most likely even then the reg-map won't change drastically, if
> at all. So we could ignore the PID4, otherwise we check PID4 in this
> driver and adapt the behavior.

I am just looking for ARM MHU implementation, not any non-ARM MHU.
If look at the MHU spec[1], excerpts below:

PID_4 Register

[31:8]	-	Reserved. Read as zero.
[7:4]	SIZE	Indicates the log2 of the number of 4KB blocks that the 
interface occupies. Set to 0x0.
[3:0]	DES_2	JEP106 continuation code that identifies the designer. Set 
to 0x4 for ARM.

PID_1 Register

[31:8]	-	Reserved. Read as zero.
[7:4]	DES_0	Bits [3:0] of the JEP Identity. Set to 0xB for ARM.
[3:0]	PART_1	Bits [11:8] of the part number. Set to 0x0.

Now by skipping PID4 DES_2 part, you are not comparing the designer
correctly. It may be OK to fix in the driver as you mentioned.
Not sure if it's better to fix AMBA, or just don't use AMBA for
IP with JEP106 code. I don't have any strong opinion there.

Regards,
Sudeep

[1] 
http://infocenter.arm.com/help/topic/com.arm.doc.ddi0515b/CHDBFACE.html#id5278622

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sudeep Holla March 18, 2015, 2:23 p.m. UTC | #6
On 18/03/15 13:19, Jassi Brar wrote:
> On Wed, Mar 18, 2015 at 3:55 PM, Sudeep Holla <sudeep.holla@arm.com> wrote:
>>
>>> +static int mhu_send_data(struct mbox_chan *chan, void *data)
>>> +{
>>> +       struct mhu_link *mlink = chan->con_priv;
>>> +       u32 *arg = data;
>>
>> Arnd doesn't like this and had suggestions in some other thread.
>>
> No, Arnd suggested doing it this way. And another platform's driver
> was made to do this way.
>

IIUC he suggested that it's better to add another interface/API
to pass fixed-length something like

inline int mbox_send_message_u32(struct mbox_chan *chan, u32 msg)
{
	mbox_send_message(chan, &msg, sizeof(msg));
}

and add a length argument to the existing mbox_send_message like:

int mbox_send_message(struct mbox_chan *chan, void *mssg, int length)

Am I missing something here ?

>>> +       writel_relaxed(*arg, mlink->tx_reg + INTR_SET_OFS);
>>> +
>>> +       return 0;
>>> +}
>>> +
>>> +static int mhu_startup(struct mbox_chan *chan)
>>> +{
>>> +       struct mhu_link *mlink = chan->con_priv;
>>> +       u32 val;
>>> +       int ret;
>>> +
>>> +       val = readl_relaxed(mlink->tx_reg + INTR_STAT_OFS);
>>> +       writel_relaxed(val, mlink->tx_reg + INTR_CLR_OFS);
>>> +
>>> +       ret = request_irq(mlink->irq, mhu_rx_interrupt,
>>> +                         IRQF_SHARED, "mhu_link", chan);
>>
>>
>> Any reason we can't move this to probe and have {en,dis}able_irq here if
>> needed. I has seen it was too heavy to have these especially when
>> sending small packets.
>>
> I see you used to do memcpy in irq-handler
> https://git.linaro.org/landing-teams/working/arm/kernel.git/blob/HEAD:/drivers/mailbox/arm_mhu.c
> perhaps you were using your old driver?
>

That driver is too old and long abandoned. It mixes up the protocol
details and was written when mailbox f/w was still under discussion.
So you can forget that, it's out of scope of this discussion.

> If you use this new driver, and send packets so often that
> request-release irq has effect, maybe should hold the mailbox
> reference for lifetime. I remember suggesting you that already and I
> remember you said that's how it was.
>

Ah right, I keep getting confused that ops->startup is called from
mbox_send_message for no reason, sorry for the noise. However,
I found threaded_irq is much better for large packets.

Regards,
Sudeep

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Sudeep Holla March 26, 2015, 11:43 a.m. UTC | #7
On 04/03/15 11:01, Vincent Yang wrote:
> From: Jassi Brar <jaswinder.singh@linaro.org>
>
> Add driver for the ARM Primecell Message-Handling-Unit(MHU) controller.
>
> Signed-off-by: Jassi Brar <jaswinder.singh@linaro.org>
> Signed-off-by: Andy Green <andy.green@linaro.org>
> Signed-off-by: Vincent Yang <vincent.yang@socionext.com>
> Signed-off-by: Tetsuya Nuriya <nuriya.tetsuya@socionext.com>
> ---
>   .../devicetree/bindings/mailbox/arm-mhu.txt        |  43 +++++
>   drivers/mailbox/Kconfig                            |   9 +
>   drivers/mailbox/Makefile                           |   2 +
>   drivers/mailbox/arm_mhu.c                          | 195 +++++++++++++++++++++
>   4 files changed, 249 insertions(+)
>   create mode 100644 Documentation/devicetree/bindings/mailbox/arm-mhu.txt
>   create mode 100644 drivers/mailbox/arm_mhu.c
>
> diff --git a/Documentation/devicetree/bindings/mailbox/arm-mhu.txt b/Documentation/devicetree/bindings/mailbox/arm-mhu.txt
> new file mode 100644
> index 0000000..4971f03
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/mailbox/arm-mhu.txt
> @@ -0,0 +1,43 @@
> +ARM MHU Mailbox Driver
> +======================
> +
> +The ARM's Message-Handling-Unit (MHU) is a mailbox controller that has
> +3 independent channels/links to communicate with remote processor(s).
> + MHU links are hardwired on a platform. A link raises interrupt for any
> +received data. However, there is no specified way of knowing if the sent
> +data has been read by the remote. This driver assumes the sender polls
> +STAT register and the remote clears it after having read the data.
> +The last channel is specified to be a 'Secure' resource, hence can't be
> +used by Linux running NS.
> +
> +Mailbox Device Node:
> +====================
> +
> +Required properties:
> +--------------------
> +- compatible:		Shall be "arm,mhu" & "arm,primecell"
> +- reg:			Contains the mailbox register address range (base
> +			address and length)
> +- #mbox-cells		Shall be 1 - the index of the channel needed.
> +- interrupts:		Contains the interrupt information corresponding to
> +			each of the 3 links of MHU.
> +

I tried using this driver and found that AMBA driver expects apb_clk
without which probe fails. Though your example have it, it's not
explicit from the binding. Also AMBA binding expects the primecell id in
the binding.

Regards,
Sudeep

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Russell King - ARM Linux March 26, 2015, 11:49 a.m. UTC | #8
On Thu, Mar 26, 2015 at 11:43:21AM +0000, Sudeep Holla wrote:
> I tried using this driver and found that AMBA driver expects apb_clk
> without which probe fails. Though your example have it, it's not
> explicit from the binding. Also AMBA binding expects the primecell id in
> the binding.

That's optional:

Optional properties:

- arm,primecell-periphid : Value to override the h/w value with

It's only required when the hardware doesn't provide the correct value.
Sudeep Holla March 26, 2015, 11:58 a.m. UTC | #9
On 26/03/15 11:49, Russell King - ARM Linux wrote:
> On Thu, Mar 26, 2015 at 11:43:21AM +0000, Sudeep Holla wrote:
>> I tried using this driver and found that AMBA driver expects apb_clk
>> without which probe fails. Though your example have it, it's not
>> explicit from the binding. Also AMBA binding expects the primecell id in
>> the binding.
>
> That's optional:
>
> Optional properties:
>
> - arm,primecell-periphid : Value to override the h/w value with
>
> It's only required when the hardware doesn't provide the correct value.
>

Ah sorry my bad, I meant the compatible(somehow left this word at the
end of earlier email - it should have been" .. AMBA binding expects the
primecell id in the binding compatible")

- compatible : should be a specific name for the peripheral and
	"arm,primecell". The specific name will match the ARM
	engineering name for the logic block in the form: "arm,pl???"

So I wanted to make sure either we follow that here(unlikely as ARM is
not publishing this as standard primecell yet) or specify that it's
exception here.

Regards,
Sudeep

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/Documentation/devicetree/bindings/mailbox/arm-mhu.txt b/Documentation/devicetree/bindings/mailbox/arm-mhu.txt
new file mode 100644
index 0000000..4971f03
--- /dev/null
+++ b/Documentation/devicetree/bindings/mailbox/arm-mhu.txt
@@ -0,0 +1,43 @@ 
+ARM MHU Mailbox Driver
+======================
+
+The ARM's Message-Handling-Unit (MHU) is a mailbox controller that has
+3 independent channels/links to communicate with remote processor(s).
+ MHU links are hardwired on a platform. A link raises interrupt for any
+received data. However, there is no specified way of knowing if the sent
+data has been read by the remote. This driver assumes the sender polls
+STAT register and the remote clears it after having read the data.
+The last channel is specified to be a 'Secure' resource, hence can't be
+used by Linux running NS.
+
+Mailbox Device Node:
+====================
+
+Required properties:
+--------------------
+- compatible:		Shall be "arm,mhu" & "arm,primecell"
+- reg:			Contains the mailbox register address range (base
+			address and length)
+- #mbox-cells		Shall be 1 - the index of the channel needed.
+- interrupts:		Contains the interrupt information corresponding to
+			each of the 3 links of MHU.
+
+Example:
+--------
+
+	mhu: mailbox@2b1f0000 {
+		#mbox-cells = <1>;
+		compatible = "arm,mhu", "arm,primecell";
+		reg = <0 0x2b1f0000 0x1000>;
+		interrupts = <0 36 4>, /* LP-NonSecure */
+			     <0 35 4>, /* HP-NonSecure */
+			     <0 37 4>; /* Secure */
+		clocks = <&clock 0 2 1>;
+		clock-names = "apb_pclk";
+	};
+
+	mhu_client: scb@2e000000 {
+		compatible = "fujitsu,mb86s70-scb-1.0";
+		reg = <0 0x2e000000 0x4000>;
+		mboxes = <&mhu 1>; /* HP-NonSecure */
+	};
diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
index 84325f2..84b0a2d 100644
--- a/drivers/mailbox/Kconfig
+++ b/drivers/mailbox/Kconfig
@@ -6,6 +6,15 @@  menuconfig MAILBOX
 	  signals. Say Y if your platform supports hardware mailboxes.
 
 if MAILBOX
+
+config ARM_MHU
+	tristate "ARM MHU Mailbox"
+	depends on ARM_AMBA
+	help
+	  Say Y here if you want to build the ARM MHU controller driver.
+	  The controller has 3 mailbox channels, the last of which can be
+	  used in Secure mode only.
+
 config PL320_MBOX
 	bool "ARM PL320 Mailbox"
 	depends on ARM_AMBA
diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
index 2e79231..b18201e 100644
--- a/drivers/mailbox/Makefile
+++ b/drivers/mailbox/Makefile
@@ -2,6 +2,8 @@ 
 
 obj-$(CONFIG_MAILBOX)		+= mailbox.o
 
+obj-$(CONFIG_ARM_MHU)	+= arm_mhu.o
+
 obj-$(CONFIG_PL320_MBOX)	+= pl320-ipc.o
 
 obj-$(CONFIG_OMAP2PLUS_MBOX)	+= omap-mailbox.o
diff --git a/drivers/mailbox/arm_mhu.c b/drivers/mailbox/arm_mhu.c
new file mode 100644
index 0000000..ac693c6
--- /dev/null
+++ b/drivers/mailbox/arm_mhu.c
@@ -0,0 +1,195 @@ 
+/*
+ * Copyright (C) 2013-2015 Fujitsu Semiconductor Ltd.
+ * Copyright (C) 2015 Linaro Ltd.
+ * Author: Jassi Brar <jaswinder.singh@linaro.org>
+ *
+ * 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/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/amba/bus.h>
+#include <linux/mailbox_controller.h>
+
+#define INTR_STAT_OFS	0x0
+#define INTR_SET_OFS	0x8
+#define INTR_CLR_OFS	0x10
+
+#define MHU_LP_OFFSET	0x0
+#define MHU_HP_OFFSET	0x20
+#define MHU_SEC_OFFSET	0x200
+#define TX_REG_OFFSET	0x100
+
+#define MHU_CHANS	3
+
+struct mhu_link {
+	unsigned irq;
+	void __iomem *tx_reg;
+	void __iomem *rx_reg;
+};
+
+struct arm_mhu {
+	void __iomem *base;
+	struct mhu_link mlink[MHU_CHANS];
+	struct mbox_chan chan[MHU_CHANS];
+	struct mbox_controller mbox;
+};
+
+static irqreturn_t mhu_rx_interrupt(int irq, void *p)
+{
+	struct mbox_chan *chan = p;
+	struct mhu_link *mlink = chan->con_priv;
+	u32 val;
+
+	val = readl_relaxed(mlink->rx_reg + INTR_STAT_OFS);
+	if (!val)
+		return IRQ_NONE;
+
+	mbox_chan_received_data(chan, (void *)&val);
+
+	writel_relaxed(val, mlink->rx_reg + INTR_CLR_OFS);
+
+	return IRQ_HANDLED;
+}
+
+static bool mhu_last_tx_done(struct mbox_chan *chan)
+{
+	struct mhu_link *mlink = chan->con_priv;
+	u32 val = readl_relaxed(mlink->tx_reg + INTR_STAT_OFS);
+
+	return (val == 0);
+}
+
+static int mhu_send_data(struct mbox_chan *chan, void *data)
+{
+	struct mhu_link *mlink = chan->con_priv;
+	u32 *arg = data;
+
+	writel_relaxed(*arg, mlink->tx_reg + INTR_SET_OFS);
+
+	return 0;
+}
+
+static int mhu_startup(struct mbox_chan *chan)
+{
+	struct mhu_link *mlink = chan->con_priv;
+	u32 val;
+	int ret;
+
+	val = readl_relaxed(mlink->tx_reg + INTR_STAT_OFS);
+	writel_relaxed(val, mlink->tx_reg + INTR_CLR_OFS);
+
+	ret = request_irq(mlink->irq, mhu_rx_interrupt,
+			  IRQF_SHARED, "mhu_link", chan);
+	if (ret) {
+		dev_err(chan->mbox->dev,
+			"Unable to aquire IRQ %d\n", mlink->irq);
+		return ret;
+	}
+
+	return 0;
+}
+
+static void mhu_shutdown(struct mbox_chan *chan)
+{
+	struct mhu_link *mlink = chan->con_priv;
+
+	free_irq(mlink->irq, chan);
+}
+
+static struct mbox_chan_ops mhu_ops = {
+	.send_data = mhu_send_data,
+	.startup = mhu_startup,
+	.shutdown = mhu_shutdown,
+	.last_tx_done = mhu_last_tx_done,
+};
+
+static int mhu_probe(struct amba_device *adev, const struct amba_id *id)
+{
+	int i, err;
+	struct arm_mhu *mhu;
+	struct device *dev = &adev->dev;
+	int mhu_reg[MHU_CHANS] = {MHU_LP_OFFSET, MHU_HP_OFFSET, MHU_SEC_OFFSET};
+
+	/* Allocate memory for device */
+	mhu = devm_kzalloc(dev, sizeof(*mhu), GFP_KERNEL);
+	if (!mhu)
+		return -ENOMEM;
+
+	mhu->base = devm_ioremap_resource(dev, &adev->res);
+	if (IS_ERR(mhu->base)) {
+		dev_err(dev, "ioremap failed\n");
+		return PTR_ERR(mhu->base);
+	}
+
+	for (i = 0; i < MHU_CHANS; i++) {
+		mhu->chan[i].con_priv = &mhu->mlink[i];
+		mhu->mlink[i].irq = adev->irq[i];
+		mhu->mlink[i].rx_reg = mhu->base + mhu_reg[i];
+		mhu->mlink[i].tx_reg = mhu->mlink[i].rx_reg + TX_REG_OFFSET;
+	}
+
+	mhu->mbox.dev = dev;
+	mhu->mbox.chans = &mhu->chan[0];
+	mhu->mbox.num_chans = MHU_CHANS;
+	mhu->mbox.ops = &mhu_ops;
+	mhu->mbox.txdone_irq = false;
+	mhu->mbox.txdone_poll = true;
+	mhu->mbox.txpoll_period = 10;
+
+	amba_set_drvdata(adev, mhu);
+
+	err = mbox_controller_register(&mhu->mbox);
+	if (err) {
+		dev_err(dev, "Failed to register mailboxes %d\n", err);
+		return err;
+	}
+
+	dev_info(dev, "ARM MHU Mailbox registered\n");
+	return 0;
+}
+
+static int mhu_remove(struct amba_device *adev)
+{
+	struct arm_mhu *mhu = amba_get_drvdata(adev);
+
+	mbox_controller_unregister(&mhu->mbox);
+
+	return 0;
+}
+
+static struct amba_id mhu_ids[] = {
+	{
+		.id	= 0x1bb098,
+		.mask	= 0xffffff,
+	},
+	{ 0, 0 },
+};
+MODULE_DEVICE_TABLE(amba, mhu_ids);
+
+static struct amba_driver arm_mhu_driver = {
+	.drv = {
+		.name	= "mhu",
+	},
+	.id_table	= mhu_ids,
+	.probe		= mhu_probe,
+	.remove		= mhu_remove,
+};
+module_amba_driver(arm_mhu_driver);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("ARM MHU Driver");
+MODULE_AUTHOR("Jassi Brar <jassisinghbrar@gmail.com>");