Commit 14ba9a2e authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'mailbox-devel' of git://git.linaro.org/landing-teams/working/fujitsu/integration

Pull mailbox framework updates from Jassi Brar.

* 'mailbox-devel' of git://git.linaro.org/landing-teams/working/fujitsu/integration:
  Mailbox: Add support for Platform Communication Channel
  mailbox/omap: adapt to the new mailbox framework
  mailbox: add tx_prepare client callback
  mailbox: Don't unnecessarily re-arm the polling timer
parents b859e7d1 86c22f8c
......@@ -43,6 +43,9 @@ Required properties:
device. The format is dependent on which interrupt
controller the OMAP device uses
- ti,hwmods: Name of the hwmod associated with the mailbox
- #mbox-cells: Common mailbox binding property to identify the number
of cells required for the mailbox specifier. Should be
1
- ti,mbox-num-users: Number of targets (processor devices) that the mailbox
device can interrupt
- ti,mbox-num-fifos: Number of h/w fifo queues within the mailbox IP block
......@@ -72,6 +75,18 @@ data that represent the following:
Cell #3 (usr_id) - mailbox user id for identifying the interrupt line
associated with generating a tx/rx fifo interrupt.
Mailbox Users:
==============
A device needing to communicate with a target processor device should specify
them using the common mailbox binding properties, "mboxes" and the optional
"mbox-names" (please see Documentation/devicetree/bindings/mailbox/mailbox.txt
for details). Each value of the mboxes property should contain a phandle to the
mailbox controller device node and an args specifier that will be the phandle to
the intended sub-mailbox child node to be used for communication. The equivalent
"mbox-names" property value can be used to give a name to the communication channel
to be used by the client user.
Example:
--------
......@@ -81,6 +96,7 @@ mailbox: mailbox@4a0f4000 {
reg = <0x4a0f4000 0x200>;
interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
ti,hwmods = "mailbox";
#mbox-cells = <1>;
ti,mbox-num-users = <3>;
ti,mbox-num-fifos = <8>;
mbox_ipu: mbox_ipu {
......@@ -93,12 +109,19 @@ mailbox: mailbox@4a0f4000 {
};
};
dsp {
...
mboxes = <&mailbox &mbox_dsp>;
...
};
/* AM33xx */
mailbox: mailbox@480C8000 {
compatible = "ti,omap4-mailbox";
reg = <0x480C8000 0x200>;
interrupts = <77>;
ti,hwmods = "mailbox";
#mbox-cells = <1>;
ti,mbox-num-users = <4>;
ti,mbox-num-fifos = <8>;
mbox_wkupm3: wkup_m3 {
......
......@@ -33,4 +33,16 @@ config OMAP_MBOX_KFIFO_SIZE
Specify the default size of mailbox's kfifo buffers (bytes).
This can also be changed at runtime (via the mbox_kfifo_size
module parameter).
config PCC
bool "Platform Communication Channel Driver"
depends on ACPI
help
ACPI 5.0+ spec defines a generic mode of communication
between the OS and a platform such as the BMC. This medium
(PCC) is typically used by CPPC (ACPI CPU Performance management),
RAS (ACPI reliability protocol) and MPST (ACPI Memory power
states). Select this driver if your platform implements the
PCC clients mentioned above.
endif
......@@ -5,3 +5,5 @@ obj-$(CONFIG_MAILBOX) += mailbox.o
obj-$(CONFIG_PL320_MBOX) += pl320-ipc.o
obj-$(CONFIG_OMAP2PLUS_MBOX) += omap-mailbox.o
obj-$(CONFIG_PCC) += pcc.o
......@@ -21,13 +21,13 @@
#include <linux/mailbox_client.h>
#include <linux/mailbox_controller.h>
#define TXDONE_BY_IRQ BIT(0) /* controller has remote RTR irq */
#define TXDONE_BY_POLL BIT(1) /* controller can read status of last TX */
#define TXDONE_BY_ACK BIT(2) /* S/W ACK recevied by Client ticks the TX */
#include "mailbox.h"
static LIST_HEAD(mbox_cons);
static DEFINE_MUTEX(con_mutex);
static void poll_txdone(unsigned long data);
static int add_to_rbuf(struct mbox_chan *chan, void *mssg)
{
int idx;
......@@ -60,7 +60,7 @@ static void msg_submit(struct mbox_chan *chan)
unsigned count, idx;
unsigned long flags;
void *data;
int err;
int err = -EBUSY;
spin_lock_irqsave(&chan->lock, flags);
......@@ -76,6 +76,8 @@ static void msg_submit(struct mbox_chan *chan)
data = chan->msg_data[idx];
if (chan->cl->tx_prepare)
chan->cl->tx_prepare(chan->cl, data);
/* Try to submit a message to the MBOX controller */
err = chan->mbox->ops->send_data(chan, data);
if (!err) {
......@@ -84,6 +86,9 @@ static void msg_submit(struct mbox_chan *chan)
}
exit:
spin_unlock_irqrestore(&chan->lock, flags);
if (!err && chan->txdone_method == TXDONE_BY_POLL)
poll_txdone((unsigned long)chan->mbox);
}
static void tx_tick(struct mbox_chan *chan, int r)
......@@ -117,10 +122,11 @@ static void poll_txdone(unsigned long data)
struct mbox_chan *chan = &mbox->chans[i];
if (chan->active_req && chan->cl) {
resched = true;
txdone = chan->mbox->ops->last_tx_done(chan);
if (txdone)
tx_tick(chan, 0);
else
resched = true;
}
}
......@@ -252,9 +258,6 @@ int mbox_send_message(struct mbox_chan *chan, void *mssg)
msg_submit(chan);
if (chan->txdone_method == TXDONE_BY_POLL)
poll_txdone((unsigned long)chan->mbox);
if (chan->cl->tx_block && chan->active_req) {
unsigned long wait;
int ret;
......
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#ifndef __MAILBOX_H
#define __MAILBOX_H
#define TXDONE_BY_IRQ BIT(0) /* controller has remote RTR irq */
#define TXDONE_BY_POLL BIT(1) /* controller can read status of last TX */
#define TXDONE_BY_ACK BIT(2) /* S/W ACK recevied by Client ticks the TX */
#endif /* __MAILBOX_H */
This diff is collapsed.
This diff is collapsed.
......@@ -27,6 +27,7 @@
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/remoteproc.h>
#include <linux/mailbox_client.h>
#include <linux/omap-mailbox.h>
#include <linux/platform_data/remoteproc-omap.h>
......@@ -36,20 +37,19 @@
/**
* struct omap_rproc - omap remote processor state
* @mbox: omap mailbox handle
* @nb: notifier block that will be invoked on inbound mailbox messages
* @mbox: mailbox channel handle
* @client: mailbox client to request the mailbox channel
* @rproc: rproc handle
*/
struct omap_rproc {
struct omap_mbox *mbox;
struct notifier_block nb;
struct mbox_chan *mbox;
struct mbox_client client;
struct rproc *rproc;
};
/**
* omap_rproc_mbox_callback() - inbound mailbox message handler
* @this: notifier block
* @index: unused
* @client: mailbox client pointer used for requesting the mailbox channel
* @data: mailbox payload
*
* This handler is invoked by omap's mailbox driver whenever a mailbox
......@@ -61,13 +61,13 @@ struct omap_rproc {
* that indicates different events. Those values are deliberately very
* big so they don't coincide with virtqueue indices.
*/
static int omap_rproc_mbox_callback(struct notifier_block *this,
unsigned long index, void *data)
static void omap_rproc_mbox_callback(struct mbox_client *client, void *data)
{
mbox_msg_t msg = (mbox_msg_t) data;
struct omap_rproc *oproc = container_of(this, struct omap_rproc, nb);
struct omap_rproc *oproc = container_of(client, struct omap_rproc,
client);
struct device *dev = oproc->rproc->dev.parent;
const char *name = oproc->rproc->name;
u32 msg = (u32)data;
dev_dbg(dev, "mbox msg: 0x%x\n", msg);
......@@ -84,8 +84,6 @@ static int omap_rproc_mbox_callback(struct notifier_block *this,
if (rproc_vq_interrupt(oproc->rproc, msg) == IRQ_NONE)
dev_dbg(dev, "no message was found in vqid %d\n", msg);
}
return NOTIFY_DONE;
}
/* kick a virtqueue */
......@@ -96,8 +94,8 @@ static void omap_rproc_kick(struct rproc *rproc, int vqid)
int ret;
/* send the index of the triggered virtqueue in the mailbox payload */
ret = omap_mbox_msg_send(oproc->mbox, vqid);
if (ret)
ret = mbox_send_message(oproc->mbox, (void *)vqid);
if (ret < 0)
dev_err(dev, "omap_mbox_msg_send failed: %d\n", ret);
}
......@@ -115,17 +113,22 @@ static int omap_rproc_start(struct rproc *rproc)
struct platform_device *pdev = to_platform_device(dev);
struct omap_rproc_pdata *pdata = pdev->dev.platform_data;
int ret;
struct mbox_client *client = &oproc->client;
if (pdata->set_bootaddr)
pdata->set_bootaddr(rproc->bootaddr);
oproc->nb.notifier_call = omap_rproc_mbox_callback;
client->dev = dev;
client->tx_done = NULL;
client->rx_callback = omap_rproc_mbox_callback;
client->tx_block = false;
client->knows_txdone = false;
/* every omap rproc is assigned a mailbox instance for messaging */
oproc->mbox = omap_mbox_get(pdata->mbox_name, &oproc->nb);
oproc->mbox = omap_mbox_request_channel(client, pdata->mbox_name);
if (IS_ERR(oproc->mbox)) {
ret = PTR_ERR(oproc->mbox);
dev_err(dev, "omap_mbox_get failed: %d\n", ret);
ret = -EBUSY;
dev_err(dev, "mbox_request_channel failed: %ld\n",
PTR_ERR(oproc->mbox));
return ret;
}
......@@ -136,9 +139,9 @@ static int omap_rproc_start(struct rproc *rproc)
* Note that the reply will _not_ arrive immediately: this message
* will wait in the mailbox fifo until the remote processor is booted.
*/
ret = omap_mbox_msg_send(oproc->mbox, RP_MBOX_ECHO_REQUEST);
if (ret) {
dev_err(dev, "omap_mbox_get failed: %d\n", ret);
ret = mbox_send_message(oproc->mbox, (void *)RP_MBOX_ECHO_REQUEST);
if (ret < 0) {
dev_err(dev, "mbox_send_message failed: %d\n", ret);
goto put_mbox;
}
......@@ -151,7 +154,7 @@ static int omap_rproc_start(struct rproc *rproc)
return 0;
put_mbox:
omap_mbox_put(oproc->mbox, &oproc->nb);
mbox_free_channel(oproc->mbox);
return ret;
}
......@@ -168,7 +171,7 @@ static int omap_rproc_stop(struct rproc *rproc)
if (ret)
return ret;
omap_mbox_put(oproc->mbox, &oproc->nb);
mbox_free_channel(oproc->mbox);
return 0;
}
......
......@@ -25,6 +25,8 @@ struct mbox_chan;
* if the client receives some ACK packet for transmission.
* Unused if the controller already has TX_Done/RTR IRQ.
* @rx_callback: Atomic callback to provide client the data received
* @tx_prepare: Atomic callback to ask client to prepare the payload
* before initiating the transmission if required.
* @tx_done: Atomic callback to tell client of data transmission
*/
struct mbox_client {
......@@ -34,6 +36,7 @@ struct mbox_client {
bool knows_txdone;
void (*rx_callback)(struct mbox_client *cl, void *mssg);
void (*tx_prepare)(struct mbox_client *cl, void *mssg);
void (*tx_done)(struct mbox_client *cl, void *mssg, int r);
};
......
......@@ -10,20 +10,20 @@
#define OMAP_MAILBOX_H
typedef u32 mbox_msg_t;
struct omap_mbox;
typedef int __bitwise omap_mbox_irq_t;
#define IRQ_TX ((__force omap_mbox_irq_t) 1)
#define IRQ_RX ((__force omap_mbox_irq_t) 2)
int omap_mbox_msg_send(struct omap_mbox *, mbox_msg_t msg);
struct mbox_chan;
struct mbox_client;
struct omap_mbox *omap_mbox_get(const char *, struct notifier_block *nb);
void omap_mbox_put(struct omap_mbox *mbox, struct notifier_block *nb);
struct mbox_chan *omap_mbox_request_channel(struct mbox_client *cl,
const char *chan_name);
void omap_mbox_save_ctx(struct omap_mbox *mbox);
void omap_mbox_restore_ctx(struct omap_mbox *mbox);
void omap_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq);
void omap_mbox_disable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq);
void omap_mbox_save_ctx(struct mbox_chan *chan);
void omap_mbox_restore_ctx(struct mbox_chan *chan);
void omap_mbox_enable_irq(struct mbox_chan *chan, omap_mbox_irq_t irq);
void omap_mbox_disable_irq(struct mbox_chan *chan, omap_mbox_irq_t irq);
#endif /* OMAP_MAILBOX_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment