aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-10-21 14:21:19 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-10-21 14:21:19 -0400
commit43d451f163c1b615c1bedef95258c49712679eeb (patch)
tree52ed78b04435ffbd663a902bbd5bdb69a65ad584
parent21d2271fd0812ebe3716cab0b48356837485a74d (diff)
parent9f3e3cacb2ffdefe28c7cf490bf543e4dcb2770a (diff)
Merge branch 'mailbox-for-linus' of git://git.linaro.org/landing-teams/working/fujitsu/integration
Pull mailbox framework from Jassi Brar: "A framework for Mailbox controllers and clients have been cooking for more than a year now. Everybody in the CC list had been copied on patchset revisions and most of them have made sounds of approval, though just one concrete Reviewed-by. The patchset has also been in linux-next for a couple of weeks now and no conflict has been reported. The framework has the backing of at least 5 platforms, though I can't say if/when they upstream their drivers (some businesses have 'changed')" (Further acked-by by Arnd Bergmann and Suman Anna in the pull request thread) * 'mailbox-for-linus' of git://git.linaro.org/landing-teams/working/fujitsu/integration: dt: mailbox: add generic bindings doc: add documentation for mailbox framework mailbox: Introduce framework for mailbox mailbox: rename pl320-ipc specific mailbox.h
-rw-r--r--Documentation/devicetree/bindings/mailbox/mailbox.txt38
-rw-r--r--Documentation/mailbox.txt122
-rw-r--r--MAINTAINERS8
-rw-r--r--arch/arm/mach-highbank/highbank.c2
-rw-r--r--drivers/cpufreq/highbank-cpufreq.c2
-rw-r--r--drivers/mailbox/Makefile4
-rw-r--r--drivers/mailbox/mailbox.c465
-rw-r--r--drivers/mailbox/pl320-ipc.c2
-rw-r--r--include/linux/mailbox_client.h46
-rw-r--r--include/linux/mailbox_controller.h133
-rw-r--r--include/linux/pl320-ipc.h (renamed from include/linux/mailbox.h)0
11 files changed, 819 insertions, 3 deletions
diff --git a/Documentation/devicetree/bindings/mailbox/mailbox.txt b/Documentation/devicetree/bindings/mailbox/mailbox.txt
new file mode 100644
index 000000000000..1a2cd3d266db
--- /dev/null
+++ b/Documentation/devicetree/bindings/mailbox/mailbox.txt
@@ -0,0 +1,38 @@
1* Generic Mailbox Controller and client driver bindings
2
3Generic binding to provide a way for Mailbox controller drivers to
4assign appropriate mailbox channel to client drivers.
5
6* Mailbox Controller
7
8Required property:
9- #mbox-cells: Must be at least 1. Number of cells in a mailbox
10 specifier.
11
12Example:
13 mailbox: mailbox {
14 ...
15 #mbox-cells = <1>;
16 };
17
18
19* Mailbox Client
20
21Required property:
22- mboxes: List of phandle and mailbox channel specifiers.
23
24Optional property:
25- mbox-names: List of identifier strings for each mailbox channel
26 required by the client. The use of this property
27 is discouraged in favor of using index in list of
28 'mboxes' while requesting a mailbox. Instead the
29 platforms may define channel indices, in DT headers,
30 to something legible.
31
32Example:
33 pwr_cntrl: power {
34 ...
35 mbox-names = "pwr-ctrl", "rpc";
36 mboxes = <&mailbox 0
37 &mailbox 1>;
38 };
diff --git a/Documentation/mailbox.txt b/Documentation/mailbox.txt
new file mode 100644
index 000000000000..60f43ff629aa
--- /dev/null
+++ b/Documentation/mailbox.txt
@@ -0,0 +1,122 @@
1 The Common Mailbox Framework
2 Jassi Brar <jaswinder.singh@linaro.org>
3
4 This document aims to help developers write client and controller
5drivers for the API. But before we start, let us note that the
6client (especially) and controller drivers are likely going to be
7very platform specific because the remote firmware is likely to be
8proprietary and implement non-standard protocol. So even if two
9platforms employ, say, PL320 controller, the client drivers can't
10be shared across them. Even the PL320 driver might need to accommodate
11some platform specific quirks. So the API is meant mainly to avoid
12similar copies of code written for each platform. Having said that,
13nothing prevents the remote f/w to also be Linux based and use the
14same api there. However none of that helps us locally because we only
15ever deal at client's protocol level.
16 Some of the choices made during implementation are the result of this
17peculiarity of this "common" framework.
18
19
20
21 Part 1 - Controller Driver (See include/linux/mailbox_controller.h)
22
23 Allocate mbox_controller and the array of mbox_chan.
24Populate mbox_chan_ops, except peek_data() all are mandatory.
25The controller driver might know a message has been consumed
26by the remote by getting an IRQ or polling some hardware flag
27or it can never know (the client knows by way of the protocol).
28The method in order of preference is IRQ -> Poll -> None, which
29the controller driver should set via 'txdone_irq' or 'txdone_poll'
30or neither.
31
32
33 Part 2 - Client Driver (See include/linux/mailbox_client.h)
34
35 The client might want to operate in blocking mode (synchronously
36send a message through before returning) or non-blocking/async mode (submit
37a message and a callback function to the API and return immediately).
38
39
40struct demo_client {
41 struct mbox_client cl;
42 struct mbox_chan *mbox;
43 struct completion c;
44 bool async;
45 /* ... */
46};
47
48/*
49 * This is the handler for data received from remote. The behaviour is purely
50 * dependent upon the protocol. This is just an example.
51 */
52static void message_from_remote(struct mbox_client *cl, void *mssg)
53{
54 struct demo_client *dc = container_of(mbox_client,
55 struct demo_client, cl);
56 if (dc->aysnc) {
57 if (is_an_ack(mssg)) {
58 /* An ACK to our last sample sent */
59 return; /* Or do something else here */
60 } else { /* A new message from remote */
61 queue_req(mssg);
62 }
63 } else {
64 /* Remote f/w sends only ACK packets on this channel */
65 return;
66 }
67}
68
69static void sample_sent(struct mbox_client *cl, void *mssg, int r)
70{
71 struct demo_client *dc = container_of(mbox_client,
72 struct demo_client, cl);
73 complete(&dc->c);
74}
75
76static void client_demo(struct platform_device *pdev)
77{
78 struct demo_client *dc_sync, *dc_async;
79 /* The controller already knows async_pkt and sync_pkt */
80 struct async_pkt ap;
81 struct sync_pkt sp;
82
83 dc_sync = kzalloc(sizeof(*dc_sync), GFP_KERNEL);
84 dc_async = kzalloc(sizeof(*dc_async), GFP_KERNEL);
85
86 /* Populate non-blocking mode client */
87 dc_async->cl.dev = &pdev->dev;
88 dc_async->cl.rx_callback = message_from_remote;
89 dc_async->cl.tx_done = sample_sent;
90 dc_async->cl.tx_block = false;
91 dc_async->cl.tx_tout = 0; /* doesn't matter here */
92 dc_async->cl.knows_txdone = false; /* depending upon protocol */
93 dc_async->async = true;
94 init_completion(&dc_async->c);
95
96 /* Populate blocking mode client */
97 dc_sync->cl.dev = &pdev->dev;
98 dc_sync->cl.rx_callback = message_from_remote;
99 dc_sync->cl.tx_done = NULL; /* operate in blocking mode */
100 dc_sync->cl.tx_block = true;
101 dc_sync->cl.tx_tout = 500; /* by half a second */
102 dc_sync->cl.knows_txdone = false; /* depending upon protocol */
103 dc_sync->async = false;
104
105 /* ASync mailbox is listed second in 'mboxes' property */
106 dc_async->mbox = mbox_request_channel(&dc_async->cl, 1);
107 /* Populate data packet */
108 /* ap.xxx = 123; etc */
109 /* Send async message to remote */
110 mbox_send_message(dc_async->mbox, &ap);
111
112 /* Sync mailbox is listed first in 'mboxes' property */
113 dc_sync->mbox = mbox_request_channel(&dc_sync->cl, 0);
114 /* Populate data packet */
115 /* sp.abc = 123; etc */
116 /* Send message to remote in blocking mode */
117 mbox_send_message(dc_sync->mbox, &sp);
118 /* At this point 'sp' has been sent */
119
120 /* Now wait for async chan to be done */
121 wait_for_completion(&dc_async->c);
122}
diff --git a/MAINTAINERS b/MAINTAINERS
index a20df9bf8ab0..b4b05dd4ffe3 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -5834,6 +5834,14 @@ S: Maintained
5834F: drivers/net/macvlan.c 5834F: drivers/net/macvlan.c
5835F: include/linux/if_macvlan.h 5835F: include/linux/if_macvlan.h
5836 5836
5837MAILBOX API
5838M: Jassi Brar <jassisinghbrar@gmail.com>
5839L: linux-kernel@vger.kernel.org
5840S: Maintained
5841F: drivers/mailbox/
5842F: include/linux/mailbox_client.h
5843F: include/linux/mailbox_controller.h
5844
5837MAN-PAGES: MANUAL PAGES FOR LINUX -- Sections 2, 3, 4, 5, and 7 5845MAN-PAGES: MANUAL PAGES FOR LINUX -- Sections 2, 3, 4, 5, and 7
5838M: Michael Kerrisk <mtk.manpages@gmail.com> 5846M: Michael Kerrisk <mtk.manpages@gmail.com>
5839W: http://www.kernel.org/doc/man-pages 5847W: http://www.kernel.org/doc/man-pages
diff --git a/arch/arm/mach-highbank/highbank.c b/arch/arm/mach-highbank/highbank.c
index 8c35ae4ff176..07a09570175d 100644
--- a/arch/arm/mach-highbank/highbank.c
+++ b/arch/arm/mach-highbank/highbank.c
@@ -20,7 +20,7 @@
20#include <linux/input.h> 20#include <linux/input.h>
21#include <linux/io.h> 21#include <linux/io.h>
22#include <linux/irqchip.h> 22#include <linux/irqchip.h>
23#include <linux/mailbox.h> 23#include <linux/pl320-ipc.h>
24#include <linux/of.h> 24#include <linux/of.h>
25#include <linux/of_irq.h> 25#include <linux/of_irq.h>
26#include <linux/of_platform.h> 26#include <linux/of_platform.h>
diff --git a/drivers/cpufreq/highbank-cpufreq.c b/drivers/cpufreq/highbank-cpufreq.c
index ec399ad2f059..1608f7105c9f 100644
--- a/drivers/cpufreq/highbank-cpufreq.c
+++ b/drivers/cpufreq/highbank-cpufreq.c
@@ -19,7 +19,7 @@
19#include <linux/cpu.h> 19#include <linux/cpu.h>
20#include <linux/err.h> 20#include <linux/err.h>
21#include <linux/of.h> 21#include <linux/of.h>
22#include <linux/mailbox.h> 22#include <linux/pl320-ipc.h>
23#include <linux/platform_device.h> 23#include <linux/platform_device.h>
24 24
25#define HB_CPUFREQ_CHANGE_NOTE 0x80000001 25#define HB_CPUFREQ_CHANGE_NOTE 0x80000001
diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
index 6d184dbcaca8..94ed7cefb14d 100644
--- a/drivers/mailbox/Makefile
+++ b/drivers/mailbox/Makefile
@@ -1,3 +1,7 @@
1# Generic MAILBOX API
2
3obj-$(CONFIG_MAILBOX) += mailbox.o
4
1obj-$(CONFIG_PL320_MBOX) += pl320-ipc.o 5obj-$(CONFIG_PL320_MBOX) += pl320-ipc.o
2 6
3obj-$(CONFIG_OMAP2PLUS_MBOX) += omap-mailbox.o 7obj-$(CONFIG_OMAP2PLUS_MBOX) += omap-mailbox.o
diff --git a/drivers/mailbox/mailbox.c b/drivers/mailbox/mailbox.c
new file mode 100644
index 000000000000..afcb430508ec
--- /dev/null
+++ b/drivers/mailbox/mailbox.c
@@ -0,0 +1,465 @@
1/*
2 * Mailbox: Common code for Mailbox controllers and users
3 *
4 * Copyright (C) 2013-2014 Linaro Ltd.
5 * Author: Jassi Brar <jassisinghbrar@gmail.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include <linux/interrupt.h>
13#include <linux/spinlock.h>
14#include <linux/mutex.h>
15#include <linux/delay.h>
16#include <linux/slab.h>
17#include <linux/err.h>
18#include <linux/module.h>
19#include <linux/device.h>
20#include <linux/bitops.h>
21#include <linux/mailbox_client.h>
22#include <linux/mailbox_controller.h>
23
24#define TXDONE_BY_IRQ BIT(0) /* controller has remote RTR irq */
25#define TXDONE_BY_POLL BIT(1) /* controller can read status of last TX */
26#define TXDONE_BY_ACK BIT(2) /* S/W ACK recevied by Client ticks the TX */
27
28static LIST_HEAD(mbox_cons);
29static DEFINE_MUTEX(con_mutex);
30
31static int add_to_rbuf(struct mbox_chan *chan, void *mssg)
32{
33 int idx;
34 unsigned long flags;
35
36 spin_lock_irqsave(&chan->lock, flags);
37
38 /* See if there is any space left */
39 if (chan->msg_count == MBOX_TX_QUEUE_LEN) {
40 spin_unlock_irqrestore(&chan->lock, flags);
41 return -ENOBUFS;
42 }
43
44 idx = chan->msg_free;
45 chan->msg_data[idx] = mssg;
46 chan->msg_count++;
47
48 if (idx == MBOX_TX_QUEUE_LEN - 1)
49 chan->msg_free = 0;
50 else
51 chan->msg_free++;
52
53 spin_unlock_irqrestore(&chan->lock, flags);
54
55 return idx;
56}
57
58static void msg_submit(struct mbox_chan *chan)
59{
60 unsigned count, idx;
61 unsigned long flags;
62 void *data;
63 int err;
64
65 spin_lock_irqsave(&chan->lock, flags);
66
67 if (!chan->msg_count || chan->active_req)
68 goto exit;
69
70 count = chan->msg_count;
71 idx = chan->msg_free;
72 if (idx >= count)
73 idx -= count;
74 else
75 idx += MBOX_TX_QUEUE_LEN - count;
76
77 data = chan->msg_data[idx];
78
79 /* Try to submit a message to the MBOX controller */
80 err = chan->mbox->ops->send_data(chan, data);
81 if (!err) {
82 chan->active_req = data;
83 chan->msg_count--;
84 }
85exit:
86 spin_unlock_irqrestore(&chan->lock, flags);
87}
88
89static void tx_tick(struct mbox_chan *chan, int r)
90{
91 unsigned long flags;
92 void *mssg;
93
94 spin_lock_irqsave(&chan->lock, flags);
95 mssg = chan->active_req;
96 chan->active_req = NULL;
97 spin_unlock_irqrestore(&chan->lock, flags);
98
99 /* Submit next message */
100 msg_submit(chan);
101
102 /* Notify the client */
103 if (mssg && chan->cl->tx_done)
104 chan->cl->tx_done(chan->cl, mssg, r);
105
106 if (chan->cl->tx_block)
107 complete(&chan->tx_complete);
108}
109
110static void poll_txdone(unsigned long data)
111{
112 struct mbox_controller *mbox = (struct mbox_controller *)data;
113 bool txdone, resched = false;
114 int i;
115
116 for (i = 0; i < mbox->num_chans; i++) {
117 struct mbox_chan *chan = &mbox->chans[i];
118
119 if (chan->active_req && chan->cl) {
120 resched = true;
121 txdone = chan->mbox->ops->last_tx_done(chan);
122 if (txdone)
123 tx_tick(chan, 0);
124 }
125 }
126
127 if (resched)
128 mod_timer(&mbox->poll, jiffies +
129 msecs_to_jiffies(mbox->txpoll_period));
130}
131
132/**
133 * mbox_chan_received_data - A way for controller driver to push data
134 * received from remote to the upper layer.
135 * @chan: Pointer to the mailbox channel on which RX happened.
136 * @mssg: Client specific message typecasted as void *
137 *
138 * After startup and before shutdown any data received on the chan
139 * is passed on to the API via atomic mbox_chan_received_data().
140 * The controller should ACK the RX only after this call returns.
141 */
142void mbox_chan_received_data(struct mbox_chan *chan, void *mssg)
143{
144 /* No buffering the received data */
145 if (chan->cl->rx_callback)
146 chan->cl->rx_callback(chan->cl, mssg);
147}
148EXPORT_SYMBOL_GPL(mbox_chan_received_data);
149
150/**
151 * mbox_chan_txdone - A way for controller driver to notify the
152 * framework that the last TX has completed.
153 * @chan: Pointer to the mailbox chan on which TX happened.
154 * @r: Status of last TX - OK or ERROR
155 *
156 * The controller that has IRQ for TX ACK calls this atomic API
157 * to tick the TX state machine. It works only if txdone_irq
158 * is set by the controller.
159 */
160void mbox_chan_txdone(struct mbox_chan *chan, int r)
161{
162 if (unlikely(!(chan->txdone_method & TXDONE_BY_IRQ))) {
163 dev_err(chan->mbox->dev,
164 "Controller can't run the TX ticker\n");
165 return;
166 }
167
168 tx_tick(chan, r);
169}
170EXPORT_SYMBOL_GPL(mbox_chan_txdone);
171
172/**
173 * mbox_client_txdone - The way for a client to run the TX state machine.
174 * @chan: Mailbox channel assigned to this client.
175 * @r: Success status of last transmission.
176 *
177 * The client/protocol had received some 'ACK' packet and it notifies
178 * the API that the last packet was sent successfully. This only works
179 * if the controller can't sense TX-Done.
180 */
181void mbox_client_txdone(struct mbox_chan *chan, int r)
182{
183 if (unlikely(!(chan->txdone_method & TXDONE_BY_ACK))) {
184 dev_err(chan->mbox->dev, "Client can't run the TX ticker\n");
185 return;
186 }
187
188 tx_tick(chan, r);
189}
190EXPORT_SYMBOL_GPL(mbox_client_txdone);
191
192/**
193 * mbox_client_peek_data - A way for client driver to pull data
194 * received from remote by the controller.
195 * @chan: Mailbox channel assigned to this client.
196 *
197 * A poke to controller driver for any received data.
198 * The data is actually passed onto client via the
199 * mbox_chan_received_data()
200 * The call can be made from atomic context, so the controller's
201 * implementation of peek_data() must not sleep.
202 *
203 * Return: True, if controller has, and is going to push after this,
204 * some data.
205 * False, if controller doesn't have any data to be read.
206 */
207bool mbox_client_peek_data(struct mbox_chan *chan)
208{
209 if (chan->mbox->ops->peek_data)
210 return chan->mbox->ops->peek_data(chan);
211
212 return false;
213}
214EXPORT_SYMBOL_GPL(mbox_client_peek_data);
215
216/**
217 * mbox_send_message - For client to submit a message to be
218 * sent to the remote.
219 * @chan: Mailbox channel assigned to this client.
220 * @mssg: Client specific message typecasted.
221 *
222 * For client to submit data to the controller destined for a remote
223 * processor. If the client had set 'tx_block', the call will return
224 * either when the remote receives the data or when 'tx_tout' millisecs
225 * run out.
226 * In non-blocking mode, the requests are buffered by the API and a
227 * non-negative token is returned for each queued request. If the request
228 * is not queued, a negative token is returned. Upon failure or successful
229 * TX, the API calls 'tx_done' from atomic context, from which the client
230 * could submit yet another request.
231 * The pointer to message should be preserved until it is sent
232 * over the chan, i.e, tx_done() is made.
233 * This function could be called from atomic context as it simply
234 * queues the data and returns a token against the request.
235 *
236 * Return: Non-negative integer for successful submission (non-blocking mode)
237 * or transmission over chan (blocking mode).
238 * Negative value denotes failure.
239 */
240int mbox_send_message(struct mbox_chan *chan, void *mssg)
241{
242 int t;
243
244 if (!chan || !chan->cl)
245 return -EINVAL;
246
247 t = add_to_rbuf(chan, mssg);
248 if (t < 0) {
249 dev_err(chan->mbox->dev, "Try increasing MBOX_TX_QUEUE_LEN\n");
250 return t;
251 }
252
253 msg_submit(chan);
254
255 if (chan->txdone_method == TXDONE_BY_POLL)
256 poll_txdone((unsigned long)chan->mbox);
257
258 if (chan->cl->tx_block && chan->active_req) {
259 unsigned long wait;
260 int ret;
261
262 if (!chan->cl->tx_tout) /* wait forever */
263 wait = msecs_to_jiffies(3600000);
264 else
265 wait = msecs_to_jiffies(chan->cl->tx_tout);
266
267 ret = wait_for_completion_timeout(&chan->tx_complete, wait);
268 if (ret == 0) {
269 t = -EIO;
270 tx_tick(chan, -EIO);
271 }
272 }
273
274 return t;
275}
276EXPORT_SYMBOL_GPL(mbox_send_message);
277
278/**
279 * mbox_request_channel - Request a mailbox channel.
280 * @cl: Identity of the client requesting the channel.
281 * @index: Index of mailbox specifier in 'mboxes' property.
282 *
283 * The Client specifies its requirements and capabilities while asking for
284 * a mailbox channel. It can't be called from atomic context.
285 * The channel is exclusively allocated and can't be used by another
286 * client before the owner calls mbox_free_channel.
287 * After assignment, any packet received on this channel will be
288 * handed over to the client via the 'rx_callback'.
289 * The framework holds reference to the client, so the mbox_client
290 * structure shouldn't be modified until the mbox_free_channel returns.
291 *
292 * Return: Pointer to the channel assigned to the client if successful.
293 * ERR_PTR for request failure.
294 */
295struct mbox_chan *mbox_request_channel(struct mbox_client *cl, int index)
296{
297 struct device *dev = cl->dev;
298 struct mbox_controller *mbox;
299 struct of_phandle_args spec;
300 struct mbox_chan *chan;
301 unsigned long flags;
302 int ret;
303
304 if (!dev || !dev->of_node) {
305 pr_debug("%s: No owner device node\n", __func__);
306 return ERR_PTR(-ENODEV);
307 }
308
309 mutex_lock(&con_mutex);
310
311 if (of_parse_phandle_with_args(dev->of_node, "mboxes",
312 "#mbox-cells", index, &spec)) {
313 dev_dbg(dev, "%s: can't parse \"mboxes\" property\n", __func__);
314 mutex_unlock(&con_mutex);
315 return ERR_PTR(-ENODEV);
316 }
317
318 chan = NULL;
319 list_for_each_entry(mbox, &mbox_cons, node)
320 if (mbox->dev->of_node == spec.np) {
321 chan = mbox->of_xlate(mbox, &spec);
322 break;
323 }
324
325 of_node_put(spec.np);
326
327 if (!chan || chan->cl || !try_module_get(mbox->dev->driver->owner)) {
328 dev_dbg(dev, "%s: mailbox not free\n", __func__);
329 mutex_unlock(&con_mutex);
330 return ERR_PTR(-EBUSY);
331 }
332
333 spin_lock_irqsave(&chan->lock, flags);
334 chan->msg_free = 0;
335 chan->msg_count = 0;
336 chan->active_req = NULL;
337 chan->cl = cl;
338 init_completion(&chan->tx_complete);
339
340 if (chan->txdone_method == TXDONE_BY_POLL && cl->knows_txdone)
341 chan->txdone_method |= TXDONE_BY_ACK;
342
343 spin_unlock_irqrestore(&chan->lock, flags);
344
345 ret = chan->mbox->ops->startup(chan);
346 if (ret) {
347 dev_err(dev, "Unable to startup the chan (%d)\n", ret);
348 mbox_free_channel(chan);
349 chan = ERR_PTR(ret);
350 }
351
352 mutex_unlock(&con_mutex);
353 return chan;
354}
355EXPORT_SYMBOL_GPL(mbox_request_channel);
356
357/**
358 * mbox_free_channel - The client relinquishes control of a mailbox
359 * channel by this call.
360 * @chan: The mailbox channel to be freed.
361 */
362void mbox_free_channel(struct mbox_chan *chan)
363{
364 unsigned long flags;
365
366 if (!chan || !chan->cl)
367 return;
368
369 chan->mbox->ops->shutdown(chan);
370
371 /* The queued TX requests are simply aborted, no callbacks are made */
372 spin_lock_irqsave(&chan->lock, flags);
373 chan->cl = NULL;
374 chan->active_req = NULL;
375 if (chan->txdone_method == (TXDONE_BY_POLL | TXDONE_BY_ACK))
376 chan->txdone_method = TXDONE_BY_POLL;
377
378 module_put(chan->mbox->dev->driver->owner);
379 spin_unlock_irqrestore(&chan->lock, flags);
380}
381EXPORT_SYMBOL_GPL(mbox_free_channel);
382
383static struct mbox_chan *
384of_mbox_index_xlate(struct mbox_controller *mbox,
385 const struct of_phandle_args *sp)
386{
387 int ind = sp->args[0];
388
389 if (ind >= mbox->num_chans)
390 return NULL;
391
392 return &mbox->chans[ind];
393}
394
395/**
396 * mbox_controller_register - Register the mailbox controller
397 * @mbox: Pointer to the mailbox controller.
398 *
399 * The controller driver registers its communication channels
400 */
401int mbox_controller_register(struct mbox_controller *mbox)
402{
403 int i, txdone;
404
405 /* Sanity check */
406 if (!mbox || !mbox->dev || !mbox->ops || !mbox->num_chans)
407 return -EINVAL;
408
409 if (mbox->txdone_irq)
410 txdone = TXDONE_BY_IRQ;
411 else if (mbox->txdone_poll)
412 txdone = TXDONE_BY_POLL;
413 else /* It has to be ACK then */
414 txdone = TXDONE_BY_ACK;
415
416 if (txdone == TXDONE_BY_POLL) {
417 mbox->poll.function = &poll_txdone;
418 mbox->poll.data = (unsigned long)mbox;
419 init_timer(&mbox->poll);
420 }
421
422 for (i = 0; i < mbox->num_chans; i++) {
423 struct mbox_chan *chan = &mbox->chans[i];
424
425 chan->cl = NULL;
426 chan->mbox = mbox;
427 chan->txdone_method = txdone;
428 spin_lock_init(&chan->lock);
429 }
430
431 if (!mbox->of_xlate)
432 mbox->of_xlate = of_mbox_index_xlate;
433
434 mutex_lock(&con_mutex);
435 list_add_tail(&mbox->node, &mbox_cons);
436 mutex_unlock(&con_mutex);
437
438 return 0;
439}
440EXPORT_SYMBOL_GPL(mbox_controller_register);
441
442/**
443 * mbox_controller_unregister - Unregister the mailbox controller
444 * @mbox: Pointer to the mailbox controller.
445 */
446void mbox_controller_unregister(struct mbox_controller *mbox)
447{
448 int i;
449
450 if (!mbox)
451 return;
452
453 mutex_lock(&con_mutex);
454
455 list_del(&mbox->node);
456
457 for (i = 0; i < mbox->num_chans; i++)
458 mbox_free_channel(&mbox->chans[i]);
459
460 if (mbox->txdone_poll)
461 del_timer_sync(&mbox->poll);
462
463 mutex_unlock(&con_mutex);
464}
465EXPORT_SYMBOL_GPL(mbox_controller_unregister);
diff --git a/drivers/mailbox/pl320-ipc.c b/drivers/mailbox/pl320-ipc.c
index d873cbae2fbb..f3755e0aa935 100644
--- a/drivers/mailbox/pl320-ipc.c
+++ b/drivers/mailbox/pl320-ipc.c
@@ -26,7 +26,7 @@
26#include <linux/device.h> 26#include <linux/device.h>
27#include <linux/amba/bus.h> 27#include <linux/amba/bus.h>
28 28
29#include <linux/mailbox.h> 29#include <linux/pl320-ipc.h>
30 30
31#define IPCMxSOURCE(m) ((m) * 0x40) 31#define IPCMxSOURCE(m) ((m) * 0x40)
32#define IPCMxDSET(m) (((m) * 0x40) + 0x004) 32#define IPCMxDSET(m) (((m) * 0x40) + 0x004)
diff --git a/include/linux/mailbox_client.h b/include/linux/mailbox_client.h
new file mode 100644
index 000000000000..307d9cab2026
--- /dev/null
+++ b/include/linux/mailbox_client.h
@@ -0,0 +1,46 @@
1/*
2 * Copyright (C) 2013-2014 Linaro Ltd.
3 * Author: Jassi Brar <jassisinghbrar@gmail.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 */
9
10#ifndef __MAILBOX_CLIENT_H
11#define __MAILBOX_CLIENT_H
12
13#include <linux/of.h>
14#include <linux/device.h>
15
16struct mbox_chan;
17
18/**
19 * struct mbox_client - User of a mailbox
20 * @dev: The client device
21 * @tx_block: If the mbox_send_message should block until data is
22 * transmitted.
23 * @tx_tout: Max block period in ms before TX is assumed failure
24 * @knows_txdone: If the client could run the TX state machine. Usually
25 * if the client receives some ACK packet for transmission.
26 * Unused if the controller already has TX_Done/RTR IRQ.
27 * @rx_callback: Atomic callback to provide client the data received
28 * @tx_done: Atomic callback to tell client of data transmission
29 */
30struct mbox_client {
31 struct device *dev;
32 bool tx_block;
33 unsigned long tx_tout;
34 bool knows_txdone;
35
36 void (*rx_callback)(struct mbox_client *cl, void *mssg);
37 void (*tx_done)(struct mbox_client *cl, void *mssg, int r);
38};
39
40struct mbox_chan *mbox_request_channel(struct mbox_client *cl, int index);
41int mbox_send_message(struct mbox_chan *chan, void *mssg);
42void mbox_client_txdone(struct mbox_chan *chan, int r); /* atomic */
43bool mbox_client_peek_data(struct mbox_chan *chan); /* atomic */
44void mbox_free_channel(struct mbox_chan *chan); /* may sleep */
45
46#endif /* __MAILBOX_CLIENT_H */
diff --git a/include/linux/mailbox_controller.h b/include/linux/mailbox_controller.h
new file mode 100644
index 000000000000..d4cf96f07cfc
--- /dev/null
+++ b/include/linux/mailbox_controller.h
@@ -0,0 +1,133 @@
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License version 2 as
4 * published by the Free Software Foundation.
5 */
6
7#ifndef __MAILBOX_CONTROLLER_H
8#define __MAILBOX_CONTROLLER_H
9
10#include <linux/of.h>
11#include <linux/types.h>
12#include <linux/timer.h>
13#include <linux/device.h>
14#include <linux/completion.h>
15
16struct mbox_chan;
17
18/**
19 * struct mbox_chan_ops - methods to control mailbox channels
20 * @send_data: The API asks the MBOX controller driver, in atomic
21 * context try to transmit a message on the bus. Returns 0 if
22 * data is accepted for transmission, -EBUSY while rejecting
23 * if the remote hasn't yet read the last data sent. Actual
24 * transmission of data is reported by the controller via
25 * mbox_chan_txdone (if it has some TX ACK irq). It must not
26 * sleep.
27 * @startup: Called when a client requests the chan. The controller
28 * could ask clients for additional parameters of communication
29 * to be provided via client's chan_data. This call may
30 * block. After this call the Controller must forward any
31 * data received on the chan by calling mbox_chan_received_data.
32 * The controller may do stuff that need to sleep.
33 * @shutdown: Called when a client relinquishes control of a chan.
34 * This call may block too. The controller must not forward
35 * any received data anymore.
36 * The controller may do stuff that need to sleep.
37 * @last_tx_done: If the controller sets 'txdone_poll', the API calls
38 * this to poll status of last TX. The controller must
39 * give priority to IRQ method over polling and never
40 * set both txdone_poll and txdone_irq. Only in polling
41 * mode 'send_data' is expected to return -EBUSY.
42 * The controller may do stuff that need to sleep/block.
43 * Used only if txdone_poll:=true && txdone_irq:=false
44 * @peek_data: Atomic check for any received data. Return true if controller
45 * has some data to push to the client. False otherwise.
46 */
47struct mbox_chan_ops {
48 int (*send_data)(struct mbox_chan *chan, void *data);
49 int (*startup)(struct mbox_chan *chan);
50 void (*shutdown)(struct mbox_chan *chan);
51 bool (*last_tx_done)(struct mbox_chan *chan);
52 bool (*peek_data)(struct mbox_chan *chan);
53};
54
55/**
56 * struct mbox_controller - Controller of a class of communication channels
57 * @dev: Device backing this controller
58 * @ops: Operators that work on each communication chan
59 * @chans: Array of channels
60 * @num_chans: Number of channels in the 'chans' array.
61 * @txdone_irq: Indicates if the controller can report to API when
62 * the last transmitted data was read by the remote.
63 * Eg, if it has some TX ACK irq.
64 * @txdone_poll: If the controller can read but not report the TX
65 * done. Ex, some register shows the TX status but
66 * no interrupt rises. Ignored if 'txdone_irq' is set.
67 * @txpoll_period: If 'txdone_poll' is in effect, the API polls for
68 * last TX's status after these many millisecs
69 * @of_xlate: Controller driver specific mapping of channel via DT
70 * @poll: API private. Used to poll for TXDONE on all channels.
71 * @node: API private. To hook into list of controllers.
72 */
73struct mbox_controller {
74 struct device *dev;
75 struct mbox_chan_ops *ops;
76 struct mbox_chan *chans;
77 int num_chans;
78 bool txdone_irq;
79 bool txdone_poll;
80 unsigned txpoll_period;
81 struct mbox_chan *(*of_xlate)(struct mbox_controller *mbox,
82 const struct of_phandle_args *sp);
83 /* Internal to API */
84 struct timer_list poll;
85 struct list_head node;
86};
87
88/*
89 * The length of circular buffer for queuing messages from a client.
90 * 'msg_count' tracks the number of buffered messages while 'msg_free'
91 * is the index where the next message would be buffered.
92 * We shouldn't need it too big because every transfer is interrupt
93 * triggered and if we have lots of data to transfer, the interrupt
94 * latencies are going to be the bottleneck, not the buffer length.
95 * Besides, mbox_send_message could be called from atomic context and
96 * the client could also queue another message from the notifier 'tx_done'
97 * of the last transfer done.
98 * REVISIT: If too many platforms see the "Try increasing MBOX_TX_QUEUE_LEN"
99 * print, it needs to be taken from config option or somesuch.
100 */
101#define MBOX_TX_QUEUE_LEN 20
102
103/**
104 * struct mbox_chan - s/w representation of a communication chan
105 * @mbox: Pointer to the parent/provider of this channel
106 * @txdone_method: Way to detect TXDone chosen by the API
107 * @cl: Pointer to the current owner of this channel
108 * @tx_complete: Transmission completion
109 * @active_req: Currently active request hook
110 * @msg_count: No. of mssg currently queued
111 * @msg_free: Index of next available mssg slot
112 * @msg_data: Hook for data packet
113 * @lock: Serialise access to the channel
114 * @con_priv: Hook for controller driver to attach private data
115 */
116struct mbox_chan {
117 struct mbox_controller *mbox;
118 unsigned txdone_method;
119 struct mbox_client *cl;
120 struct completion tx_complete;
121 void *active_req;
122 unsigned msg_count, msg_free;
123 void *msg_data[MBOX_TX_QUEUE_LEN];
124 spinlock_t lock; /* Serialise access to the channel */
125 void *con_priv;
126};
127
128int mbox_controller_register(struct mbox_controller *mbox); /* can sleep */
129void mbox_controller_unregister(struct mbox_controller *mbox); /* can sleep */
130void mbox_chan_received_data(struct mbox_chan *chan, void *data); /* atomic */
131void mbox_chan_txdone(struct mbox_chan *chan, int r); /* atomic */
132
133#endif /* __MAILBOX_CONTROLLER_H */
diff --git a/include/linux/mailbox.h b/include/linux/pl320-ipc.h
index 5161f63ec1c8..5161f63ec1c8 100644
--- a/include/linux/mailbox.h
+++ b/include/linux/pl320-ipc.h