aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-12-11 15:09:37 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2014-12-11 15:09:37 -0500
commit14ba9a2e4bacc6f5a0dbe0de5390daedd544508f (patch)
tree90b0d639f577feada25fb56837c3e8350b7de035
parentb859e7d13bcc18b56faa7e2f78db5ba8ab874a15 (diff)
parent86c22f8c9a3b71d42d38bfcd80372de72f573713 (diff)
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
-rw-r--r--Documentation/devicetree/bindings/mailbox/omap-mailbox.txt23
-rw-r--r--drivers/mailbox/Kconfig12
-rw-r--r--drivers/mailbox/Makefile2
-rw-r--r--drivers/mailbox/mailbox.c19
-rw-r--r--drivers/mailbox/mailbox.h14
-rw-r--r--drivers/mailbox/omap-mailbox.c346
-rw-r--r--drivers/mailbox/pcc.c403
-rw-r--r--drivers/remoteproc/omap_remoteproc.c51
-rw-r--r--include/linux/mailbox_client.h3
-rw-r--r--include/linux/omap-mailbox.h16
10 files changed, 701 insertions, 188 deletions
diff --git a/Documentation/devicetree/bindings/mailbox/omap-mailbox.txt b/Documentation/devicetree/bindings/mailbox/omap-mailbox.txt
index 48edc4b92afb..d1a043339c11 100644
--- a/Documentation/devicetree/bindings/mailbox/omap-mailbox.txt
+++ b/Documentation/devicetree/bindings/mailbox/omap-mailbox.txt
@@ -43,6 +43,9 @@ Required properties:
43 device. The format is dependent on which interrupt 43 device. The format is dependent on which interrupt
44 controller the OMAP device uses 44 controller the OMAP device uses
45- ti,hwmods: Name of the hwmod associated with the mailbox 45- ti,hwmods: Name of the hwmod associated with the mailbox
46- #mbox-cells: Common mailbox binding property to identify the number
47 of cells required for the mailbox specifier. Should be
48 1
46- ti,mbox-num-users: Number of targets (processor devices) that the mailbox 49- ti,mbox-num-users: Number of targets (processor devices) that the mailbox
47 device can interrupt 50 device can interrupt
48- ti,mbox-num-fifos: Number of h/w fifo queues within the mailbox IP block 51- ti,mbox-num-fifos: Number of h/w fifo queues within the mailbox IP block
@@ -72,6 +75,18 @@ data that represent the following:
72 Cell #3 (usr_id) - mailbox user id for identifying the interrupt line 75 Cell #3 (usr_id) - mailbox user id for identifying the interrupt line
73 associated with generating a tx/rx fifo interrupt. 76 associated with generating a tx/rx fifo interrupt.
74 77
78Mailbox Users:
79==============
80A device needing to communicate with a target processor device should specify
81them using the common mailbox binding properties, "mboxes" and the optional
82"mbox-names" (please see Documentation/devicetree/bindings/mailbox/mailbox.txt
83for details). Each value of the mboxes property should contain a phandle to the
84mailbox controller device node and an args specifier that will be the phandle to
85the intended sub-mailbox child node to be used for communication. The equivalent
86"mbox-names" property value can be used to give a name to the communication channel
87to be used by the client user.
88
89
75Example: 90Example:
76-------- 91--------
77 92
@@ -81,6 +96,7 @@ mailbox: mailbox@4a0f4000 {
81 reg = <0x4a0f4000 0x200>; 96 reg = <0x4a0f4000 0x200>;
82 interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>; 97 interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
83 ti,hwmods = "mailbox"; 98 ti,hwmods = "mailbox";
99 #mbox-cells = <1>;
84 ti,mbox-num-users = <3>; 100 ti,mbox-num-users = <3>;
85 ti,mbox-num-fifos = <8>; 101 ti,mbox-num-fifos = <8>;
86 mbox_ipu: mbox_ipu { 102 mbox_ipu: mbox_ipu {
@@ -93,12 +109,19 @@ mailbox: mailbox@4a0f4000 {
93 }; 109 };
94}; 110};
95 111
112dsp {
113 ...
114 mboxes = <&mailbox &mbox_dsp>;
115 ...
116};
117
96/* AM33xx */ 118/* AM33xx */
97mailbox: mailbox@480C8000 { 119mailbox: mailbox@480C8000 {
98 compatible = "ti,omap4-mailbox"; 120 compatible = "ti,omap4-mailbox";
99 reg = <0x480C8000 0x200>; 121 reg = <0x480C8000 0x200>;
100 interrupts = <77>; 122 interrupts = <77>;
101 ti,hwmods = "mailbox"; 123 ti,hwmods = "mailbox";
124 #mbox-cells = <1>;
102 ti,mbox-num-users = <4>; 125 ti,mbox-num-users = <4>;
103 ti,mbox-num-fifos = <8>; 126 ti,mbox-num-fifos = <8>;
104 mbox_wkupm3: wkup_m3 { 127 mbox_wkupm3: wkup_m3 {
diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig
index 9fd9c6717e0c..c04fed9eb15d 100644
--- a/drivers/mailbox/Kconfig
+++ b/drivers/mailbox/Kconfig
@@ -33,4 +33,16 @@ config OMAP_MBOX_KFIFO_SIZE
33 Specify the default size of mailbox's kfifo buffers (bytes). 33 Specify the default size of mailbox's kfifo buffers (bytes).
34 This can also be changed at runtime (via the mbox_kfifo_size 34 This can also be changed at runtime (via the mbox_kfifo_size
35 module parameter). 35 module parameter).
36
37config PCC
38 bool "Platform Communication Channel Driver"
39 depends on ACPI
40 help
41 ACPI 5.0+ spec defines a generic mode of communication
42 between the OS and a platform such as the BMC. This medium
43 (PCC) is typically used by CPPC (ACPI CPU Performance management),
44 RAS (ACPI reliability protocol) and MPST (ACPI Memory power
45 states). Select this driver if your platform implements the
46 PCC clients mentioned above.
47
36endif 48endif
diff --git a/drivers/mailbox/Makefile b/drivers/mailbox/Makefile
index 94ed7cefb14d..dd412c22208b 100644
--- a/drivers/mailbox/Makefile
+++ b/drivers/mailbox/Makefile
@@ -5,3 +5,5 @@ obj-$(CONFIG_MAILBOX) += mailbox.o
5obj-$(CONFIG_PL320_MBOX) += pl320-ipc.o 5obj-$(CONFIG_PL320_MBOX) += pl320-ipc.o
6 6
7obj-$(CONFIG_OMAP2PLUS_MBOX) += omap-mailbox.o 7obj-$(CONFIG_OMAP2PLUS_MBOX) += omap-mailbox.o
8
9obj-$(CONFIG_PCC) += pcc.o
diff --git a/drivers/mailbox/mailbox.c b/drivers/mailbox/mailbox.c
index afcb430508ec..59aad4d5da53 100644
--- a/drivers/mailbox/mailbox.c
+++ b/drivers/mailbox/mailbox.c
@@ -21,13 +21,13 @@
21#include <linux/mailbox_client.h> 21#include <linux/mailbox_client.h>
22#include <linux/mailbox_controller.h> 22#include <linux/mailbox_controller.h>
23 23
24#define TXDONE_BY_IRQ BIT(0) /* controller has remote RTR irq */ 24#include "mailbox.h"
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 25
28static LIST_HEAD(mbox_cons); 26static LIST_HEAD(mbox_cons);
29static DEFINE_MUTEX(con_mutex); 27static DEFINE_MUTEX(con_mutex);
30 28
29static void poll_txdone(unsigned long data);
30
31static int add_to_rbuf(struct mbox_chan *chan, void *mssg) 31static int add_to_rbuf(struct mbox_chan *chan, void *mssg)
32{ 32{
33 int idx; 33 int idx;
@@ -60,7 +60,7 @@ static void msg_submit(struct mbox_chan *chan)
60 unsigned count, idx; 60 unsigned count, idx;
61 unsigned long flags; 61 unsigned long flags;
62 void *data; 62 void *data;
63 int err; 63 int err = -EBUSY;
64 64
65 spin_lock_irqsave(&chan->lock, flags); 65 spin_lock_irqsave(&chan->lock, flags);
66 66
@@ -76,6 +76,8 @@ static void msg_submit(struct mbox_chan *chan)
76 76
77 data = chan->msg_data[idx]; 77 data = chan->msg_data[idx];
78 78
79 if (chan->cl->tx_prepare)
80 chan->cl->tx_prepare(chan->cl, data);
79 /* Try to submit a message to the MBOX controller */ 81 /* Try to submit a message to the MBOX controller */
80 err = chan->mbox->ops->send_data(chan, data); 82 err = chan->mbox->ops->send_data(chan, data);
81 if (!err) { 83 if (!err) {
@@ -84,6 +86,9 @@ static void msg_submit(struct mbox_chan *chan)
84 } 86 }
85exit: 87exit:
86 spin_unlock_irqrestore(&chan->lock, flags); 88 spin_unlock_irqrestore(&chan->lock, flags);
89
90 if (!err && chan->txdone_method == TXDONE_BY_POLL)
91 poll_txdone((unsigned long)chan->mbox);
87} 92}
88 93
89static void tx_tick(struct mbox_chan *chan, int r) 94static void tx_tick(struct mbox_chan *chan, int r)
@@ -117,10 +122,11 @@ static void poll_txdone(unsigned long data)
117 struct mbox_chan *chan = &mbox->chans[i]; 122 struct mbox_chan *chan = &mbox->chans[i];
118 123
119 if (chan->active_req && chan->cl) { 124 if (chan->active_req && chan->cl) {
120 resched = true;
121 txdone = chan->mbox->ops->last_tx_done(chan); 125 txdone = chan->mbox->ops->last_tx_done(chan);
122 if (txdone) 126 if (txdone)
123 tx_tick(chan, 0); 127 tx_tick(chan, 0);
128 else
129 resched = true;
124 } 130 }
125 } 131 }
126 132
@@ -252,9 +258,6 @@ int mbox_send_message(struct mbox_chan *chan, void *mssg)
252 258
253 msg_submit(chan); 259 msg_submit(chan);
254 260
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) { 261 if (chan->cl->tx_block && chan->active_req) {
259 unsigned long wait; 262 unsigned long wait;
260 int ret; 263 int ret;
diff --git a/drivers/mailbox/mailbox.h b/drivers/mailbox/mailbox.h
new file mode 100644
index 000000000000..456ba68513bb
--- /dev/null
+++ b/drivers/mailbox/mailbox.h
@@ -0,0 +1,14 @@
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_H
8#define __MAILBOX_H
9
10#define TXDONE_BY_IRQ BIT(0) /* controller has remote RTR irq */
11#define TXDONE_BY_POLL BIT(1) /* controller can read status of last TX */
12#define TXDONE_BY_ACK BIT(2) /* S/W ACK recevied by Client ticks the TX */
13
14#endif /* __MAILBOX_H */
diff --git a/drivers/mailbox/omap-mailbox.c b/drivers/mailbox/omap-mailbox.c
index bcc7ee129276..66b83ca94dcf 100644
--- a/drivers/mailbox/omap-mailbox.c
+++ b/drivers/mailbox/omap-mailbox.c
@@ -29,13 +29,14 @@
29#include <linux/slab.h> 29#include <linux/slab.h>
30#include <linux/kfifo.h> 30#include <linux/kfifo.h>
31#include <linux/err.h> 31#include <linux/err.h>
32#include <linux/notifier.h>
33#include <linux/module.h> 32#include <linux/module.h>
34#include <linux/of_device.h> 33#include <linux/of_device.h>
35#include <linux/platform_device.h> 34#include <linux/platform_device.h>
36#include <linux/pm_runtime.h> 35#include <linux/pm_runtime.h>
37#include <linux/platform_data/mailbox-omap.h> 36#include <linux/platform_data/mailbox-omap.h>
38#include <linux/omap-mailbox.h> 37#include <linux/omap-mailbox.h>
38#include <linux/mailbox_controller.h>
39#include <linux/mailbox_client.h>
39 40
40#define MAILBOX_REVISION 0x000 41#define MAILBOX_REVISION 0x000
41#define MAILBOX_MESSAGE(m) (0x040 + 4 * (m)) 42#define MAILBOX_MESSAGE(m) (0x040 + 4 * (m))
@@ -80,7 +81,6 @@ struct omap_mbox_queue {
80 spinlock_t lock; 81 spinlock_t lock;
81 struct kfifo fifo; 82 struct kfifo fifo;
82 struct work_struct work; 83 struct work_struct work;
83 struct tasklet_struct tasklet;
84 struct omap_mbox *mbox; 84 struct omap_mbox *mbox;
85 bool full; 85 bool full;
86}; 86};
@@ -92,6 +92,7 @@ struct omap_mbox_device {
92 u32 num_users; 92 u32 num_users;
93 u32 num_fifos; 93 u32 num_fifos;
94 struct omap_mbox **mboxes; 94 struct omap_mbox **mboxes;
95 struct mbox_controller controller;
95 struct list_head elem; 96 struct list_head elem;
96}; 97};
97 98
@@ -110,15 +111,14 @@ struct omap_mbox_fifo_info {
110struct omap_mbox { 111struct omap_mbox {
111 const char *name; 112 const char *name;
112 int irq; 113 int irq;
113 struct omap_mbox_queue *txq, *rxq; 114 struct omap_mbox_queue *rxq;
114 struct device *dev; 115 struct device *dev;
115 struct omap_mbox_device *parent; 116 struct omap_mbox_device *parent;
116 struct omap_mbox_fifo tx_fifo; 117 struct omap_mbox_fifo tx_fifo;
117 struct omap_mbox_fifo rx_fifo; 118 struct omap_mbox_fifo rx_fifo;
118 u32 ctx[OMAP4_MBOX_NR_REGS]; 119 u32 ctx[OMAP4_MBOX_NR_REGS];
119 u32 intr_type; 120 u32 intr_type;
120 int use_count; 121 struct mbox_chan *chan;
121 struct blocking_notifier_head notifier;
122}; 122};
123 123
124/* global variables for the mailbox devices */ 124/* global variables for the mailbox devices */
@@ -129,6 +129,14 @@ static unsigned int mbox_kfifo_size = CONFIG_OMAP_MBOX_KFIFO_SIZE;
129module_param(mbox_kfifo_size, uint, S_IRUGO); 129module_param(mbox_kfifo_size, uint, S_IRUGO);
130MODULE_PARM_DESC(mbox_kfifo_size, "Size of omap's mailbox kfifo (bytes)"); 130MODULE_PARM_DESC(mbox_kfifo_size, "Size of omap's mailbox kfifo (bytes)");
131 131
132static struct omap_mbox *mbox_chan_to_omap_mbox(struct mbox_chan *chan)
133{
134 if (!chan || !chan->con_priv)
135 return NULL;
136
137 return (struct omap_mbox *)chan->con_priv;
138}
139
132static inline 140static inline
133unsigned int mbox_read_reg(struct omap_mbox_device *mdev, size_t ofs) 141unsigned int mbox_read_reg(struct omap_mbox_device *mdev, size_t ofs)
134{ 142{
@@ -194,41 +202,14 @@ static int is_mbox_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
194 return (int)(enable & status & bit); 202 return (int)(enable & status & bit);
195} 203}
196 204
197/* 205void omap_mbox_save_ctx(struct mbox_chan *chan)
198 * message sender
199 */
200int omap_mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg)
201{
202 struct omap_mbox_queue *mq = mbox->txq;
203 int ret = 0, len;
204
205 spin_lock_bh(&mq->lock);
206
207 if (kfifo_avail(&mq->fifo) < sizeof(msg)) {
208 ret = -ENOMEM;
209 goto out;
210 }
211
212 if (kfifo_is_empty(&mq->fifo) && !mbox_fifo_full(mbox)) {
213 mbox_fifo_write(mbox, msg);
214 goto out;
215 }
216
217 len = kfifo_in(&mq->fifo, (unsigned char *)&msg, sizeof(msg));
218 WARN_ON(len != sizeof(msg));
219
220 tasklet_schedule(&mbox->txq->tasklet);
221
222out:
223 spin_unlock_bh(&mq->lock);
224 return ret;
225}
226EXPORT_SYMBOL(omap_mbox_msg_send);
227
228void omap_mbox_save_ctx(struct omap_mbox *mbox)
229{ 206{
230 int i; 207 int i;
231 int nr_regs; 208 int nr_regs;
209 struct omap_mbox *mbox = mbox_chan_to_omap_mbox(chan);
210
211 if (WARN_ON(!mbox))
212 return;
232 213
233 if (mbox->intr_type) 214 if (mbox->intr_type)
234 nr_regs = OMAP4_MBOX_NR_REGS; 215 nr_regs = OMAP4_MBOX_NR_REGS;
@@ -243,10 +224,14 @@ void omap_mbox_save_ctx(struct omap_mbox *mbox)
243} 224}
244EXPORT_SYMBOL(omap_mbox_save_ctx); 225EXPORT_SYMBOL(omap_mbox_save_ctx);
245 226
246void omap_mbox_restore_ctx(struct omap_mbox *mbox) 227void omap_mbox_restore_ctx(struct mbox_chan *chan)
247{ 228{
248 int i; 229 int i;
249 int nr_regs; 230 int nr_regs;
231 struct omap_mbox *mbox = mbox_chan_to_omap_mbox(chan);
232
233 if (WARN_ON(!mbox))
234 return;
250 235
251 if (mbox->intr_type) 236 if (mbox->intr_type)
252 nr_regs = OMAP4_MBOX_NR_REGS; 237 nr_regs = OMAP4_MBOX_NR_REGS;
@@ -254,14 +239,13 @@ void omap_mbox_restore_ctx(struct omap_mbox *mbox)
254 nr_regs = MBOX_NR_REGS; 239 nr_regs = MBOX_NR_REGS;
255 for (i = 0; i < nr_regs; i++) { 240 for (i = 0; i < nr_regs; i++) {
256 mbox_write_reg(mbox->parent, mbox->ctx[i], i * sizeof(u32)); 241 mbox_write_reg(mbox->parent, mbox->ctx[i], i * sizeof(u32));
257
258 dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__, 242 dev_dbg(mbox->dev, "%s: [%02x] %08x\n", __func__,
259 i, mbox->ctx[i]); 243 i, mbox->ctx[i]);
260 } 244 }
261} 245}
262EXPORT_SYMBOL(omap_mbox_restore_ctx); 246EXPORT_SYMBOL(omap_mbox_restore_ctx);
263 247
264void omap_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) 248static void _omap_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
265{ 249{
266 u32 l; 250 u32 l;
267 struct omap_mbox_fifo *fifo = (irq == IRQ_TX) ? 251 struct omap_mbox_fifo *fifo = (irq == IRQ_TX) ?
@@ -273,9 +257,8 @@ void omap_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
273 l |= bit; 257 l |= bit;
274 mbox_write_reg(mbox->parent, l, irqenable); 258 mbox_write_reg(mbox->parent, l, irqenable);
275} 259}
276EXPORT_SYMBOL(omap_mbox_enable_irq);
277 260
278void omap_mbox_disable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq) 261static void _omap_mbox_disable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
279{ 262{
280 struct omap_mbox_fifo *fifo = (irq == IRQ_TX) ? 263 struct omap_mbox_fifo *fifo = (irq == IRQ_TX) ?
281 &mbox->tx_fifo : &mbox->rx_fifo; 264 &mbox->tx_fifo : &mbox->rx_fifo;
@@ -291,28 +274,28 @@ void omap_mbox_disable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq)
291 274
292 mbox_write_reg(mbox->parent, bit, irqdisable); 275 mbox_write_reg(mbox->parent, bit, irqdisable);
293} 276}
294EXPORT_SYMBOL(omap_mbox_disable_irq);
295 277
296static void mbox_tx_tasklet(unsigned long tx_data) 278void omap_mbox_enable_irq(struct mbox_chan *chan, omap_mbox_irq_t irq)
297{ 279{
298 struct omap_mbox *mbox = (struct omap_mbox *)tx_data; 280 struct omap_mbox *mbox = mbox_chan_to_omap_mbox(chan);
299 struct omap_mbox_queue *mq = mbox->txq;
300 mbox_msg_t msg;
301 int ret;
302 281
303 while (kfifo_len(&mq->fifo)) { 282 if (WARN_ON(!mbox))
304 if (mbox_fifo_full(mbox)) { 283 return;
305 omap_mbox_enable_irq(mbox, IRQ_TX);
306 break;
307 }
308 284
309 ret = kfifo_out(&mq->fifo, (unsigned char *)&msg, 285 _omap_mbox_enable_irq(mbox, irq);
310 sizeof(msg)); 286}
311 WARN_ON(ret != sizeof(msg)); 287EXPORT_SYMBOL(omap_mbox_enable_irq);
312 288
313 mbox_fifo_write(mbox, msg); 289void omap_mbox_disable_irq(struct mbox_chan *chan, omap_mbox_irq_t irq)
314 } 290{
291 struct omap_mbox *mbox = mbox_chan_to_omap_mbox(chan);
292
293 if (WARN_ON(!mbox))
294 return;
295
296 _omap_mbox_disable_irq(mbox, irq);
315} 297}
298EXPORT_SYMBOL(omap_mbox_disable_irq);
316 299
317/* 300/*
318 * Message receiver(workqueue) 301 * Message receiver(workqueue)
@@ -328,12 +311,11 @@ static void mbox_rx_work(struct work_struct *work)
328 len = kfifo_out(&mq->fifo, (unsigned char *)&msg, sizeof(msg)); 311 len = kfifo_out(&mq->fifo, (unsigned char *)&msg, sizeof(msg));
329 WARN_ON(len != sizeof(msg)); 312 WARN_ON(len != sizeof(msg));
330 313
331 blocking_notifier_call_chain(&mq->mbox->notifier, len, 314 mbox_chan_received_data(mq->mbox->chan, (void *)msg);
332 (void *)msg);
333 spin_lock_irq(&mq->lock); 315 spin_lock_irq(&mq->lock);
334 if (mq->full) { 316 if (mq->full) {
335 mq->full = false; 317 mq->full = false;
336 omap_mbox_enable_irq(mq->mbox, IRQ_RX); 318 _omap_mbox_enable_irq(mq->mbox, IRQ_RX);
337 } 319 }
338 spin_unlock_irq(&mq->lock); 320 spin_unlock_irq(&mq->lock);
339 } 321 }
@@ -344,9 +326,9 @@ static void mbox_rx_work(struct work_struct *work)
344 */ 326 */
345static void __mbox_tx_interrupt(struct omap_mbox *mbox) 327static void __mbox_tx_interrupt(struct omap_mbox *mbox)
346{ 328{
347 omap_mbox_disable_irq(mbox, IRQ_TX); 329 _omap_mbox_disable_irq(mbox, IRQ_TX);
348 ack_mbox_irq(mbox, IRQ_TX); 330 ack_mbox_irq(mbox, IRQ_TX);
349 tasklet_schedule(&mbox->txq->tasklet); 331 mbox_chan_txdone(mbox->chan, 0);
350} 332}
351 333
352static void __mbox_rx_interrupt(struct omap_mbox *mbox) 334static void __mbox_rx_interrupt(struct omap_mbox *mbox)
@@ -357,7 +339,7 @@ static void __mbox_rx_interrupt(struct omap_mbox *mbox)
357 339
358 while (!mbox_fifo_empty(mbox)) { 340 while (!mbox_fifo_empty(mbox)) {
359 if (unlikely(kfifo_avail(&mq->fifo) < sizeof(msg))) { 341 if (unlikely(kfifo_avail(&mq->fifo) < sizeof(msg))) {
360 omap_mbox_disable_irq(mbox, IRQ_RX); 342 _omap_mbox_disable_irq(mbox, IRQ_RX);
361 mq->full = true; 343 mq->full = true;
362 goto nomem; 344 goto nomem;
363 } 345 }
@@ -388,11 +370,13 @@ static irqreturn_t mbox_interrupt(int irq, void *p)
388} 370}
389 371
390static struct omap_mbox_queue *mbox_queue_alloc(struct omap_mbox *mbox, 372static struct omap_mbox_queue *mbox_queue_alloc(struct omap_mbox *mbox,
391 void (*work) (struct work_struct *), 373 void (*work)(struct work_struct *))
392 void (*tasklet)(unsigned long))
393{ 374{
394 struct omap_mbox_queue *mq; 375 struct omap_mbox_queue *mq;
395 376
377 if (!work)
378 return NULL;
379
396 mq = kzalloc(sizeof(struct omap_mbox_queue), GFP_KERNEL); 380 mq = kzalloc(sizeof(struct omap_mbox_queue), GFP_KERNEL);
397 if (!mq) 381 if (!mq)
398 return NULL; 382 return NULL;
@@ -402,12 +386,9 @@ static struct omap_mbox_queue *mbox_queue_alloc(struct omap_mbox *mbox,
402 if (kfifo_alloc(&mq->fifo, mbox_kfifo_size, GFP_KERNEL)) 386 if (kfifo_alloc(&mq->fifo, mbox_kfifo_size, GFP_KERNEL))
403 goto error; 387 goto error;
404 388
405 if (work) 389 INIT_WORK(&mq->work, work);
406 INIT_WORK(&mq->work, work);
407
408 if (tasklet)
409 tasklet_init(&mq->tasklet, tasklet, (unsigned long)mbox);
410 return mq; 390 return mq;
391
411error: 392error:
412 kfree(mq); 393 kfree(mq);
413 return NULL; 394 return NULL;
@@ -423,71 +404,35 @@ static int omap_mbox_startup(struct omap_mbox *mbox)
423{ 404{
424 int ret = 0; 405 int ret = 0;
425 struct omap_mbox_queue *mq; 406 struct omap_mbox_queue *mq;
426 struct omap_mbox_device *mdev = mbox->parent;
427 407
428 mutex_lock(&mdev->cfg_lock); 408 mq = mbox_queue_alloc(mbox, mbox_rx_work);
429 ret = pm_runtime_get_sync(mdev->dev); 409 if (!mq)
430 if (unlikely(ret < 0)) 410 return -ENOMEM;
431 goto fail_startup; 411 mbox->rxq = mq;
432 412 mq->mbox = mbox;
433 if (!mbox->use_count++) { 413
434 mq = mbox_queue_alloc(mbox, NULL, mbox_tx_tasklet); 414 ret = request_irq(mbox->irq, mbox_interrupt, IRQF_SHARED,
435 if (!mq) { 415 mbox->name, mbox);
436 ret = -ENOMEM; 416 if (unlikely(ret)) {
437 goto fail_alloc_txq; 417 pr_err("failed to register mailbox interrupt:%d\n", ret);
438 } 418 goto fail_request_irq;
439 mbox->txq = mq; 419 }
440 420
441 mq = mbox_queue_alloc(mbox, mbox_rx_work, NULL); 421 _omap_mbox_enable_irq(mbox, IRQ_RX);
442 if (!mq) {
443 ret = -ENOMEM;
444 goto fail_alloc_rxq;
445 }
446 mbox->rxq = mq;
447 mq->mbox = mbox;
448 ret = request_irq(mbox->irq, mbox_interrupt, IRQF_SHARED,
449 mbox->name, mbox);
450 if (unlikely(ret)) {
451 pr_err("failed to register mailbox interrupt:%d\n",
452 ret);
453 goto fail_request_irq;
454 }
455 422
456 omap_mbox_enable_irq(mbox, IRQ_RX);
457 }
458 mutex_unlock(&mdev->cfg_lock);
459 return 0; 423 return 0;
460 424
461fail_request_irq: 425fail_request_irq:
462 mbox_queue_free(mbox->rxq); 426 mbox_queue_free(mbox->rxq);
463fail_alloc_rxq:
464 mbox_queue_free(mbox->txq);
465fail_alloc_txq:
466 pm_runtime_put_sync(mdev->dev);
467 mbox->use_count--;
468fail_startup:
469 mutex_unlock(&mdev->cfg_lock);
470 return ret; 427 return ret;
471} 428}
472 429
473static void omap_mbox_fini(struct omap_mbox *mbox) 430static void omap_mbox_fini(struct omap_mbox *mbox)
474{ 431{
475 struct omap_mbox_device *mdev = mbox->parent; 432 _omap_mbox_disable_irq(mbox, IRQ_RX);
476 433 free_irq(mbox->irq, mbox);
477 mutex_lock(&mdev->cfg_lock); 434 flush_work(&mbox->rxq->work);
478 435 mbox_queue_free(mbox->rxq);
479 if (!--mbox->use_count) {
480 omap_mbox_disable_irq(mbox, IRQ_RX);
481 free_irq(mbox->irq, mbox);
482 tasklet_kill(&mbox->txq->tasklet);
483 flush_work(&mbox->rxq->work);
484 mbox_queue_free(mbox->txq);
485 mbox_queue_free(mbox->rxq);
486 }
487
488 pm_runtime_put_sync(mdev->dev);
489
490 mutex_unlock(&mdev->cfg_lock);
491} 436}
492 437
493static struct omap_mbox *omap_mbox_device_find(struct omap_mbox_device *mdev, 438static struct omap_mbox *omap_mbox_device_find(struct omap_mbox_device *mdev,
@@ -509,42 +454,55 @@ static struct omap_mbox *omap_mbox_device_find(struct omap_mbox_device *mdev,
509 return mbox; 454 return mbox;
510} 455}
511 456
512struct omap_mbox *omap_mbox_get(const char *name, struct notifier_block *nb) 457struct mbox_chan *omap_mbox_request_channel(struct mbox_client *cl,
458 const char *chan_name)
513{ 459{
460 struct device *dev = cl->dev;
514 struct omap_mbox *mbox = NULL; 461 struct omap_mbox *mbox = NULL;
515 struct omap_mbox_device *mdev; 462 struct omap_mbox_device *mdev;
463 struct mbox_chan *chan;
464 unsigned long flags;
516 int ret; 465 int ret;
517 466
467 if (!dev)
468 return ERR_PTR(-ENODEV);
469
470 if (dev->of_node) {
471 pr_err("%s: please use mbox_request_channel(), this API is supported only for OMAP non-DT usage\n",
472 __func__);
473 return ERR_PTR(-ENODEV);
474 }
475
518 mutex_lock(&omap_mbox_devices_lock); 476 mutex_lock(&omap_mbox_devices_lock);
519 list_for_each_entry(mdev, &omap_mbox_devices, elem) { 477 list_for_each_entry(mdev, &omap_mbox_devices, elem) {
520 mbox = omap_mbox_device_find(mdev, name); 478 mbox = omap_mbox_device_find(mdev, chan_name);
521 if (mbox) 479 if (mbox)
522 break; 480 break;
523 } 481 }
524 mutex_unlock(&omap_mbox_devices_lock); 482 mutex_unlock(&omap_mbox_devices_lock);
525 483
526 if (!mbox) 484 if (!mbox || !mbox->chan)
527 return ERR_PTR(-ENOENT); 485 return ERR_PTR(-ENOENT);
528 486
529 if (nb) 487 chan = mbox->chan;
530 blocking_notifier_chain_register(&mbox->notifier, nb); 488 spin_lock_irqsave(&chan->lock, flags);
489 chan->msg_free = 0;
490 chan->msg_count = 0;
491 chan->active_req = NULL;
492 chan->cl = cl;
493 init_completion(&chan->tx_complete);
494 spin_unlock_irqrestore(&chan->lock, flags);
531 495
532 ret = omap_mbox_startup(mbox); 496 ret = chan->mbox->ops->startup(chan);
533 if (ret) { 497 if (ret) {
534 blocking_notifier_chain_unregister(&mbox->notifier, nb); 498 pr_err("Unable to startup the chan (%d)\n", ret);
535 return ERR_PTR(-ENODEV); 499 mbox_free_channel(chan);
500 chan = ERR_PTR(ret);
536 } 501 }
537 502
538 return mbox; 503 return chan;
539}
540EXPORT_SYMBOL(omap_mbox_get);
541
542void omap_mbox_put(struct omap_mbox *mbox, struct notifier_block *nb)
543{
544 blocking_notifier_chain_unregister(&mbox->notifier, nb);
545 omap_mbox_fini(mbox);
546} 504}
547EXPORT_SYMBOL(omap_mbox_put); 505EXPORT_SYMBOL(omap_mbox_request_channel);
548 506
549static struct class omap_mbox_class = { .name = "mbox", }; 507static struct class omap_mbox_class = { .name = "mbox", };
550 508
@@ -560,25 +518,25 @@ static int omap_mbox_register(struct omap_mbox_device *mdev)
560 mboxes = mdev->mboxes; 518 mboxes = mdev->mboxes;
561 for (i = 0; mboxes[i]; i++) { 519 for (i = 0; mboxes[i]; i++) {
562 struct omap_mbox *mbox = mboxes[i]; 520 struct omap_mbox *mbox = mboxes[i];
563 mbox->dev = device_create(&omap_mbox_class, 521 mbox->dev = device_create(&omap_mbox_class, mdev->dev,
564 mdev->dev, 0, mbox, "%s", mbox->name); 522 0, mbox, "%s", mbox->name);
565 if (IS_ERR(mbox->dev)) { 523 if (IS_ERR(mbox->dev)) {
566 ret = PTR_ERR(mbox->dev); 524 ret = PTR_ERR(mbox->dev);
567 goto err_out; 525 goto err_out;
568 } 526 }
569
570 BLOCKING_INIT_NOTIFIER_HEAD(&mbox->notifier);
571 } 527 }
572 528
573 mutex_lock(&omap_mbox_devices_lock); 529 mutex_lock(&omap_mbox_devices_lock);
574 list_add(&mdev->elem, &omap_mbox_devices); 530 list_add(&mdev->elem, &omap_mbox_devices);
575 mutex_unlock(&omap_mbox_devices_lock); 531 mutex_unlock(&omap_mbox_devices_lock);
576 532
577 return 0; 533 ret = mbox_controller_register(&mdev->controller);
578 534
579err_out: 535err_out:
580 while (i--) 536 if (ret) {
581 device_unregister(mboxes[i]->dev); 537 while (i--)
538 device_unregister(mboxes[i]->dev);
539 }
582 return ret; 540 return ret;
583} 541}
584 542
@@ -594,12 +552,64 @@ static int omap_mbox_unregister(struct omap_mbox_device *mdev)
594 list_del(&mdev->elem); 552 list_del(&mdev->elem);
595 mutex_unlock(&omap_mbox_devices_lock); 553 mutex_unlock(&omap_mbox_devices_lock);
596 554
555 mbox_controller_unregister(&mdev->controller);
556
597 mboxes = mdev->mboxes; 557 mboxes = mdev->mboxes;
598 for (i = 0; mboxes[i]; i++) 558 for (i = 0; mboxes[i]; i++)
599 device_unregister(mboxes[i]->dev); 559 device_unregister(mboxes[i]->dev);
600 return 0; 560 return 0;
601} 561}
602 562
563static int omap_mbox_chan_startup(struct mbox_chan *chan)
564{
565 struct omap_mbox *mbox = mbox_chan_to_omap_mbox(chan);
566 struct omap_mbox_device *mdev = mbox->parent;
567 int ret = 0;
568
569 mutex_lock(&mdev->cfg_lock);
570 pm_runtime_get_sync(mdev->dev);
571 ret = omap_mbox_startup(mbox);
572 if (ret)
573 pm_runtime_put_sync(mdev->dev);
574 mutex_unlock(&mdev->cfg_lock);
575 return ret;
576}
577
578static void omap_mbox_chan_shutdown(struct mbox_chan *chan)
579{
580 struct omap_mbox *mbox = mbox_chan_to_omap_mbox(chan);
581 struct omap_mbox_device *mdev = mbox->parent;
582
583 mutex_lock(&mdev->cfg_lock);
584 omap_mbox_fini(mbox);
585 pm_runtime_put_sync(mdev->dev);
586 mutex_unlock(&mdev->cfg_lock);
587}
588
589static int omap_mbox_chan_send_data(struct mbox_chan *chan, void *data)
590{
591 struct omap_mbox *mbox = mbox_chan_to_omap_mbox(chan);
592 int ret = -EBUSY;
593
594 if (!mbox)
595 return -EINVAL;
596
597 if (!mbox_fifo_full(mbox)) {
598 mbox_fifo_write(mbox, (mbox_msg_t)data);
599 ret = 0;
600 }
601
602 /* always enable the interrupt */
603 _omap_mbox_enable_irq(mbox, IRQ_TX);
604 return ret;
605}
606
607static struct mbox_chan_ops omap_mbox_chan_ops = {
608 .startup = omap_mbox_chan_startup,
609 .send_data = omap_mbox_chan_send_data,
610 .shutdown = omap_mbox_chan_shutdown,
611};
612
603static const struct of_device_id omap_mailbox_of_match[] = { 613static const struct of_device_id omap_mailbox_of_match[] = {
604 { 614 {
605 .compatible = "ti,omap2-mailbox", 615 .compatible = "ti,omap2-mailbox",
@@ -619,10 +629,35 @@ static const struct of_device_id omap_mailbox_of_match[] = {
619}; 629};
620MODULE_DEVICE_TABLE(of, omap_mailbox_of_match); 630MODULE_DEVICE_TABLE(of, omap_mailbox_of_match);
621 631
632static struct mbox_chan *omap_mbox_of_xlate(struct mbox_controller *controller,
633 const struct of_phandle_args *sp)
634{
635 phandle phandle = sp->args[0];
636 struct device_node *node;
637 struct omap_mbox_device *mdev;
638 struct omap_mbox *mbox;
639
640 mdev = container_of(controller, struct omap_mbox_device, controller);
641 if (WARN_ON(!mdev))
642 return NULL;
643
644 node = of_find_node_by_phandle(phandle);
645 if (!node) {
646 pr_err("%s: could not find node phandle 0x%x\n",
647 __func__, phandle);
648 return NULL;
649 }
650
651 mbox = omap_mbox_device_find(mdev, node->name);
652 of_node_put(node);
653 return mbox ? mbox->chan : NULL;
654}
655
622static int omap_mbox_probe(struct platform_device *pdev) 656static int omap_mbox_probe(struct platform_device *pdev)
623{ 657{
624 struct resource *mem; 658 struct resource *mem;
625 int ret; 659 int ret;
660 struct mbox_chan *chnls;
626 struct omap_mbox **list, *mbox, *mboxblk; 661 struct omap_mbox **list, *mbox, *mboxblk;
627 struct omap_mbox_pdata *pdata = pdev->dev.platform_data; 662 struct omap_mbox_pdata *pdata = pdev->dev.platform_data;
628 struct omap_mbox_dev_info *info = NULL; 663 struct omap_mbox_dev_info *info = NULL;
@@ -727,6 +762,11 @@ static int omap_mbox_probe(struct platform_device *pdev)
727 if (!list) 762 if (!list)
728 return -ENOMEM; 763 return -ENOMEM;
729 764
765 chnls = devm_kzalloc(&pdev->dev, (info_count + 1) * sizeof(*chnls),
766 GFP_KERNEL);
767 if (!chnls)
768 return -ENOMEM;
769
730 mboxblk = devm_kzalloc(&pdev->dev, info_count * sizeof(*mbox), 770 mboxblk = devm_kzalloc(&pdev->dev, info_count * sizeof(*mbox),
731 GFP_KERNEL); 771 GFP_KERNEL);
732 if (!mboxblk) 772 if (!mboxblk)
@@ -758,6 +798,8 @@ static int omap_mbox_probe(struct platform_device *pdev)
758 mbox->irq = platform_get_irq(pdev, finfo->tx_irq); 798 mbox->irq = platform_get_irq(pdev, finfo->tx_irq);
759 if (mbox->irq < 0) 799 if (mbox->irq < 0)
760 return mbox->irq; 800 return mbox->irq;
801 mbox->chan = &chnls[i];
802 chnls[i].con_priv = mbox;
761 list[i] = mbox++; 803 list[i] = mbox++;
762 } 804 }
763 805
@@ -766,6 +808,14 @@ static int omap_mbox_probe(struct platform_device *pdev)
766 mdev->num_users = num_users; 808 mdev->num_users = num_users;
767 mdev->num_fifos = num_fifos; 809 mdev->num_fifos = num_fifos;
768 mdev->mboxes = list; 810 mdev->mboxes = list;
811
812 /* OMAP does not have a Tx-Done IRQ, but rather a Tx-Ready IRQ */
813 mdev->controller.txdone_irq = true;
814 mdev->controller.dev = mdev->dev;
815 mdev->controller.ops = &omap_mbox_chan_ops;
816 mdev->controller.chans = chnls;
817 mdev->controller.num_chans = info_count;
818 mdev->controller.of_xlate = omap_mbox_of_xlate;
769 ret = omap_mbox_register(mdev); 819 ret = omap_mbox_register(mdev);
770 if (ret) 820 if (ret)
771 return ret; 821 return ret;
diff --git a/drivers/mailbox/pcc.c b/drivers/mailbox/pcc.c
new file mode 100644
index 000000000000..6dbf6fcbdfaf
--- /dev/null
+++ b/drivers/mailbox/pcc.c
@@ -0,0 +1,403 @@
1/*
2 * Copyright (C) 2014 Linaro Ltd.
3 * Author: Ashwin Chaugule <ashwin.chaugule@linaro.org>
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 as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * PCC (Platform Communication Channel) is defined in the ACPI 5.0+
16 * specification. It is a mailbox like mechanism to allow clients
17 * such as CPPC (Collaborative Processor Performance Control), RAS
18 * (Reliability, Availability and Serviceability) and MPST (Memory
19 * Node Power State Table) to talk to the platform (e.g. BMC) through
20 * shared memory regions as defined in the PCC table entries. The PCC
21 * specification supports a Doorbell mechanism for the PCC clients
22 * to notify the platform about new data. This Doorbell information
23 * is also specified in each PCC table entry. See pcc_send_data()
24 * and pcc_tx_done() for basic mode of operation.
25 *
26 * For more details about PCC, please see the ACPI specification from
27 * http://www.uefi.org/ACPIv5.1 Section 14.
28 *
29 * This file implements PCC as a Mailbox controller and allows for PCC
30 * clients to be implemented as its Mailbox Client Channels.
31 */
32
33#include <linux/acpi.h>
34#include <linux/delay.h>
35#include <linux/io.h>
36#include <linux/init.h>
37#include <linux/list.h>
38#include <linux/platform_device.h>
39#include <linux/mailbox_controller.h>
40#include <linux/mailbox_client.h>
41
42#include "mailbox.h"
43
44#define MAX_PCC_SUBSPACES 256
45#define PCCS_SS_SIG_MAGIC 0x50434300
46#define PCC_CMD_COMPLETE 0x1
47
48static struct mbox_chan *pcc_mbox_channels;
49
50static struct mbox_controller pcc_mbox_ctrl = {};
51/**
52 * get_pcc_channel - Given a PCC subspace idx, get
53 * the respective mbox_channel.
54 * @id: PCC subspace index.
55 *
56 * Return: ERR_PTR(errno) if error, else pointer
57 * to mbox channel.
58 */
59static struct mbox_chan *get_pcc_channel(int id)
60{
61 struct mbox_chan *pcc_chan;
62
63 if (id < 0 || id > pcc_mbox_ctrl.num_chans)
64 return ERR_PTR(-ENOENT);
65
66 pcc_chan = (struct mbox_chan *)
67 (unsigned long) pcc_mbox_channels +
68 (id * sizeof(*pcc_chan));
69
70 return pcc_chan;
71}
72
73/**
74 * get_subspace_id - Given a Mailbox channel, find out the
75 * PCC subspace id.
76 * @chan: Pointer to Mailbox Channel from which we want
77 * the index.
78 * Return: Errno if not found, else positive index number.
79 */
80static int get_subspace_id(struct mbox_chan *chan)
81{
82 unsigned int id = chan - pcc_mbox_channels;
83
84 if (id < 0 || id > pcc_mbox_ctrl.num_chans)
85 return -ENOENT;
86
87 return id;
88}
89
90/**
91 * pcc_mbox_request_channel - PCC clients call this function to
92 * request a pointer to their PCC subspace, from which they
93 * can get the details of communicating with the remote.
94 * @cl: Pointer to Mailbox client, so we know where to bind the
95 * Channel.
96 * @subspace_id: The PCC Subspace index as parsed in the PCC client
97 * ACPI package. This is used to lookup the array of PCC
98 * subspaces as parsed by the PCC Mailbox controller.
99 *
100 * Return: Pointer to the Mailbox Channel if successful or
101 * ERR_PTR.
102 */
103struct mbox_chan *pcc_mbox_request_channel(struct mbox_client *cl,
104 int subspace_id)
105{
106 struct device *dev = pcc_mbox_ctrl.dev;
107 struct mbox_chan *chan;
108 unsigned long flags;
109
110 /*
111 * Each PCC Subspace is a Mailbox Channel.
112 * The PCC Clients get their PCC Subspace ID
113 * from their own tables and pass it here.
114 * This returns a pointer to the PCC subspace
115 * for the Client to operate on.
116 */
117 chan = get_pcc_channel(subspace_id);
118
119 if (!chan || chan->cl) {
120 dev_err(dev, "%s: PCC mailbox not free\n", __func__);
121 return ERR_PTR(-EBUSY);
122 }
123
124 spin_lock_irqsave(&chan->lock, flags);
125 chan->msg_free = 0;
126 chan->msg_count = 0;
127 chan->active_req = NULL;
128 chan->cl = cl;
129 init_completion(&chan->tx_complete);
130
131 if (chan->txdone_method == TXDONE_BY_POLL && cl->knows_txdone)
132 chan->txdone_method |= TXDONE_BY_ACK;
133
134 spin_unlock_irqrestore(&chan->lock, flags);
135
136 return chan;
137}
138EXPORT_SYMBOL_GPL(pcc_mbox_request_channel);
139
140/**
141 * pcc_mbox_free_channel - Clients call this to free their Channel.
142 *
143 * @chan: Pointer to the mailbox channel as returned by
144 * pcc_mbox_request_channel()
145 */
146void pcc_mbox_free_channel(struct mbox_chan *chan)
147{
148 unsigned long flags;
149
150 if (!chan || !chan->cl)
151 return;
152
153 spin_lock_irqsave(&chan->lock, flags);
154 chan->cl = NULL;
155 chan->active_req = NULL;
156 if (chan->txdone_method == (TXDONE_BY_POLL | TXDONE_BY_ACK))
157 chan->txdone_method = TXDONE_BY_POLL;
158
159 spin_unlock_irqrestore(&chan->lock, flags);
160}
161EXPORT_SYMBOL_GPL(pcc_mbox_free_channel);
162
163/**
164 * pcc_tx_done - Callback from Mailbox controller code to
165 * check if PCC message transmission completed.
166 * @chan: Pointer to Mailbox channel on which previous
167 * transmission occurred.
168 *
169 * Return: TRUE if succeeded.
170 */
171static bool pcc_tx_done(struct mbox_chan *chan)
172{
173 struct acpi_pcct_hw_reduced *pcct_ss = chan->con_priv;
174 struct acpi_pcct_shared_memory *generic_comm_base =
175 (struct acpi_pcct_shared_memory *) pcct_ss->base_address;
176 u16 cmd_delay = pcct_ss->latency;
177 unsigned int retries = 0;
178
179 /* Try a few times while waiting for platform to consume */
180 while (!(readw_relaxed(&generic_comm_base->status)
181 & PCC_CMD_COMPLETE)) {
182
183 if (retries++ < 5)
184 udelay(cmd_delay);
185 else {
186 /*
187 * If the remote is dead, this will cause the Mbox
188 * controller to timeout after mbox client.tx_tout
189 * msecs.
190 */
191 pr_err("PCC platform did not respond.\n");
192 return false;
193 }
194 }
195 return true;
196}
197
198/**
199 * pcc_send_data - Called from Mailbox Controller code to finally
200 * transmit data over channel.
201 * @chan: Pointer to Mailbox channel over which to send data.
202 * @data: Actual data to be written over channel.
203 *
204 * Return: Err if something failed else 0 for success.
205 */
206static int pcc_send_data(struct mbox_chan *chan, void *data)
207{
208 struct acpi_pcct_hw_reduced *pcct_ss = chan->con_priv;
209 struct acpi_pcct_shared_memory *generic_comm_base =
210 (struct acpi_pcct_shared_memory *) pcct_ss->base_address;
211 struct acpi_generic_address doorbell;
212 u64 doorbell_preserve;
213 u64 doorbell_val;
214 u64 doorbell_write;
215 u16 cmd = *(u16 *) data;
216 u16 ss_idx = -1;
217
218 ss_idx = get_subspace_id(chan);
219
220 if (ss_idx < 0) {
221 pr_err("Invalid Subspace ID from PCC client\n");
222 return -EINVAL;
223 }
224
225 doorbell = pcct_ss->doorbell_register;
226 doorbell_preserve = pcct_ss->preserve_mask;
227 doorbell_write = pcct_ss->write_mask;
228
229 /* Write to the shared comm region. */
230 writew(cmd, &generic_comm_base->command);
231
232 /* Write Subspace MAGIC value so platform can identify destination. */
233 writel((PCCS_SS_SIG_MAGIC | ss_idx), &generic_comm_base->signature);
234
235 /* Flip CMD COMPLETE bit */
236 writew(0, &generic_comm_base->status);
237
238 /* Sync notification from OSPM to Platform. */
239 acpi_read(&doorbell_val, &doorbell);
240 acpi_write((doorbell_val & doorbell_preserve) | doorbell_write,
241 &doorbell);
242
243 return 0;
244}
245
246static struct mbox_chan_ops pcc_chan_ops = {
247 .send_data = pcc_send_data,
248 .last_tx_done = pcc_tx_done,
249};
250
251/**
252 * parse_pcc_subspace - Parse the PCC table and verify PCC subspace
253 * entries. There should be one entry per PCC client.
254 * @header: Pointer to the ACPI subtable header under the PCCT.
255 * @end: End of subtable entry.
256 *
257 * Return: 0 for Success, else errno.
258 *
259 * This gets called for each entry in the PCC table.
260 */
261static int parse_pcc_subspace(struct acpi_subtable_header *header,
262 const unsigned long end)
263{
264 struct acpi_pcct_hw_reduced *pcct_ss;
265
266 if (pcc_mbox_ctrl.num_chans <= MAX_PCC_SUBSPACES) {
267 pcct_ss = (struct acpi_pcct_hw_reduced *) header;
268
269 if (pcct_ss->header.type !=
270 ACPI_PCCT_TYPE_HW_REDUCED_SUBSPACE) {
271 pr_err("Incorrect PCC Subspace type detected\n");
272 return -EINVAL;
273 }
274 }
275
276 return 0;
277}
278
279/**
280 * acpi_pcc_probe - Parse the ACPI tree for the PCCT.
281 *
282 * Return: 0 for Success, else errno.
283 */
284static int __init acpi_pcc_probe(void)
285{
286 acpi_size pcct_tbl_header_size;
287 struct acpi_table_header *pcct_tbl;
288 struct acpi_subtable_header *pcct_entry;
289 int count, i;
290 acpi_status status = AE_OK;
291
292 /* Search for PCCT */
293 status = acpi_get_table_with_size(ACPI_SIG_PCCT, 0,
294 &pcct_tbl,
295 &pcct_tbl_header_size);
296
297 if (ACPI_FAILURE(status) || !pcct_tbl) {
298 pr_warn("PCCT header not found.\n");
299 return -ENODEV;
300 }
301
302 count = acpi_table_parse_entries(ACPI_SIG_PCCT,
303 sizeof(struct acpi_table_pcct),
304 ACPI_PCCT_TYPE_HW_REDUCED_SUBSPACE,
305 parse_pcc_subspace, MAX_PCC_SUBSPACES);
306
307 if (count <= 0) {
308 pr_err("Error parsing PCC subspaces from PCCT\n");
309 return -EINVAL;
310 }
311
312 pcc_mbox_channels = kzalloc(sizeof(struct mbox_chan) *
313 count, GFP_KERNEL);
314
315 if (!pcc_mbox_channels) {
316 pr_err("Could not allocate space for PCC mbox channels\n");
317 return -ENOMEM;
318 }
319
320 /* Point to the first PCC subspace entry */
321 pcct_entry = (struct acpi_subtable_header *) (
322 (unsigned long) pcct_tbl + sizeof(struct acpi_table_pcct));
323
324 for (i = 0; i < count; i++) {
325 pcc_mbox_channels[i].con_priv = pcct_entry;
326 pcct_entry = (struct acpi_subtable_header *)
327 ((unsigned long) pcct_entry + pcct_entry->length);
328 }
329
330 pcc_mbox_ctrl.num_chans = count;
331
332 pr_info("Detected %d PCC Subspaces\n", pcc_mbox_ctrl.num_chans);
333
334 return 0;
335}
336
337/**
338 * pcc_mbox_probe - Called when we find a match for the
339 * PCCT platform device. This is purely used to represent
340 * the PCCT as a virtual device for registering with the
341 * generic Mailbox framework.
342 *
343 * @pdev: Pointer to platform device returned when a match
344 * is found.
345 *
346 * Return: 0 for Success, else errno.
347 */
348static int pcc_mbox_probe(struct platform_device *pdev)
349{
350 int ret = 0;
351
352 pcc_mbox_ctrl.chans = pcc_mbox_channels;
353 pcc_mbox_ctrl.ops = &pcc_chan_ops;
354 pcc_mbox_ctrl.txdone_poll = true;
355 pcc_mbox_ctrl.txpoll_period = 10;
356 pcc_mbox_ctrl.dev = &pdev->dev;
357
358 pr_info("Registering PCC driver as Mailbox controller\n");
359 ret = mbox_controller_register(&pcc_mbox_ctrl);
360
361 if (ret) {
362 pr_err("Err registering PCC as Mailbox controller: %d\n", ret);
363 ret = -ENODEV;
364 }
365
366 return ret;
367}
368
369struct platform_driver pcc_mbox_driver = {
370 .probe = pcc_mbox_probe,
371 .driver = {
372 .name = "PCCT",
373 .owner = THIS_MODULE,
374 },
375};
376
377static int __init pcc_init(void)
378{
379 int ret;
380 struct platform_device *pcc_pdev;
381
382 if (acpi_disabled)
383 return -ENODEV;
384
385 /* Check if PCC support is available. */
386 ret = acpi_pcc_probe();
387
388 if (ret) {
389 pr_err("ACPI PCC probe failed.\n");
390 return -ENODEV;
391 }
392
393 pcc_pdev = platform_create_bundle(&pcc_mbox_driver,
394 pcc_mbox_probe, NULL, 0, NULL, 0);
395
396 if (!pcc_pdev) {
397 pr_err("Err creating PCC platform bundle\n");
398 return -ENODEV;
399 }
400
401 return 0;
402}
403device_initcall(pcc_init);
diff --git a/drivers/remoteproc/omap_remoteproc.c b/drivers/remoteproc/omap_remoteproc.c
index 51689721ea7a..cf92f6e7c5dc 100644
--- a/drivers/remoteproc/omap_remoteproc.c
+++ b/drivers/remoteproc/omap_remoteproc.c
@@ -27,6 +27,7 @@
27#include <linux/platform_device.h> 27#include <linux/platform_device.h>
28#include <linux/dma-mapping.h> 28#include <linux/dma-mapping.h>
29#include <linux/remoteproc.h> 29#include <linux/remoteproc.h>
30#include <linux/mailbox_client.h>
30#include <linux/omap-mailbox.h> 31#include <linux/omap-mailbox.h>
31 32
32#include <linux/platform_data/remoteproc-omap.h> 33#include <linux/platform_data/remoteproc-omap.h>
@@ -36,20 +37,19 @@
36 37
37/** 38/**
38 * struct omap_rproc - omap remote processor state 39 * struct omap_rproc - omap remote processor state
39 * @mbox: omap mailbox handle 40 * @mbox: mailbox channel handle
40 * @nb: notifier block that will be invoked on inbound mailbox messages 41 * @client: mailbox client to request the mailbox channel
41 * @rproc: rproc handle 42 * @rproc: rproc handle
42 */ 43 */
43struct omap_rproc { 44struct omap_rproc {
44 struct omap_mbox *mbox; 45 struct mbox_chan *mbox;
45 struct notifier_block nb; 46 struct mbox_client client;
46 struct rproc *rproc; 47 struct rproc *rproc;
47}; 48};
48 49
49/** 50/**
50 * omap_rproc_mbox_callback() - inbound mailbox message handler 51 * omap_rproc_mbox_callback() - inbound mailbox message handler
51 * @this: notifier block 52 * @client: mailbox client pointer used for requesting the mailbox channel
52 * @index: unused
53 * @data: mailbox payload 53 * @data: mailbox payload
54 * 54 *
55 * This handler is invoked by omap's mailbox driver whenever a mailbox 55 * This handler is invoked by omap's mailbox driver whenever a mailbox
@@ -61,13 +61,13 @@ struct omap_rproc {
61 * that indicates different events. Those values are deliberately very 61 * that indicates different events. Those values are deliberately very
62 * big so they don't coincide with virtqueue indices. 62 * big so they don't coincide with virtqueue indices.
63 */ 63 */
64static int omap_rproc_mbox_callback(struct notifier_block *this, 64static void omap_rproc_mbox_callback(struct mbox_client *client, void *data)
65 unsigned long index, void *data)
66{ 65{
67 mbox_msg_t msg = (mbox_msg_t) data; 66 struct omap_rproc *oproc = container_of(client, struct omap_rproc,
68 struct omap_rproc *oproc = container_of(this, struct omap_rproc, nb); 67 client);
69 struct device *dev = oproc->rproc->dev.parent; 68 struct device *dev = oproc->rproc->dev.parent;
70 const char *name = oproc->rproc->name; 69 const char *name = oproc->rproc->name;
70 u32 msg = (u32)data;
71 71
72 dev_dbg(dev, "mbox msg: 0x%x\n", msg); 72 dev_dbg(dev, "mbox msg: 0x%x\n", msg);
73 73
@@ -84,8 +84,6 @@ static int omap_rproc_mbox_callback(struct notifier_block *this,
84 if (rproc_vq_interrupt(oproc->rproc, msg) == IRQ_NONE) 84 if (rproc_vq_interrupt(oproc->rproc, msg) == IRQ_NONE)
85 dev_dbg(dev, "no message was found in vqid %d\n", msg); 85 dev_dbg(dev, "no message was found in vqid %d\n", msg);
86 } 86 }
87
88 return NOTIFY_DONE;
89} 87}
90 88
91/* kick a virtqueue */ 89/* kick a virtqueue */
@@ -96,8 +94,8 @@ static void omap_rproc_kick(struct rproc *rproc, int vqid)
96 int ret; 94 int ret;
97 95
98 /* send the index of the triggered virtqueue in the mailbox payload */ 96 /* send the index of the triggered virtqueue in the mailbox payload */
99 ret = omap_mbox_msg_send(oproc->mbox, vqid); 97 ret = mbox_send_message(oproc->mbox, (void *)vqid);
100 if (ret) 98 if (ret < 0)
101 dev_err(dev, "omap_mbox_msg_send failed: %d\n", ret); 99 dev_err(dev, "omap_mbox_msg_send failed: %d\n", ret);
102} 100}
103 101
@@ -115,17 +113,22 @@ static int omap_rproc_start(struct rproc *rproc)
115 struct platform_device *pdev = to_platform_device(dev); 113 struct platform_device *pdev = to_platform_device(dev);
116 struct omap_rproc_pdata *pdata = pdev->dev.platform_data; 114 struct omap_rproc_pdata *pdata = pdev->dev.platform_data;
117 int ret; 115 int ret;
116 struct mbox_client *client = &oproc->client;
118 117
119 if (pdata->set_bootaddr) 118 if (pdata->set_bootaddr)
120 pdata->set_bootaddr(rproc->bootaddr); 119 pdata->set_bootaddr(rproc->bootaddr);
121 120
122 oproc->nb.notifier_call = omap_rproc_mbox_callback; 121 client->dev = dev;
122 client->tx_done = NULL;
123 client->rx_callback = omap_rproc_mbox_callback;
124 client->tx_block = false;
125 client->knows_txdone = false;
123 126
124 /* every omap rproc is assigned a mailbox instance for messaging */ 127 oproc->mbox = omap_mbox_request_channel(client, pdata->mbox_name);
125 oproc->mbox = omap_mbox_get(pdata->mbox_name, &oproc->nb);
126 if (IS_ERR(oproc->mbox)) { 128 if (IS_ERR(oproc->mbox)) {
127 ret = PTR_ERR(oproc->mbox); 129 ret = -EBUSY;
128 dev_err(dev, "omap_mbox_get failed: %d\n", ret); 130 dev_err(dev, "mbox_request_channel failed: %ld\n",
131 PTR_ERR(oproc->mbox));
129 return ret; 132 return ret;
130 } 133 }
131 134
@@ -136,9 +139,9 @@ static int omap_rproc_start(struct rproc *rproc)
136 * Note that the reply will _not_ arrive immediately: this message 139 * Note that the reply will _not_ arrive immediately: this message
137 * will wait in the mailbox fifo until the remote processor is booted. 140 * will wait in the mailbox fifo until the remote processor is booted.
138 */ 141 */
139 ret = omap_mbox_msg_send(oproc->mbox, RP_MBOX_ECHO_REQUEST); 142 ret = mbox_send_message(oproc->mbox, (void *)RP_MBOX_ECHO_REQUEST);
140 if (ret) { 143 if (ret < 0) {
141 dev_err(dev, "omap_mbox_get failed: %d\n", ret); 144 dev_err(dev, "mbox_send_message failed: %d\n", ret);
142 goto put_mbox; 145 goto put_mbox;
143 } 146 }
144 147
@@ -151,7 +154,7 @@ static int omap_rproc_start(struct rproc *rproc)
151 return 0; 154 return 0;
152 155
153put_mbox: 156put_mbox:
154 omap_mbox_put(oproc->mbox, &oproc->nb); 157 mbox_free_channel(oproc->mbox);
155 return ret; 158 return ret;
156} 159}
157 160
@@ -168,7 +171,7 @@ static int omap_rproc_stop(struct rproc *rproc)
168 if (ret) 171 if (ret)
169 return ret; 172 return ret;
170 173
171 omap_mbox_put(oproc->mbox, &oproc->nb); 174 mbox_free_channel(oproc->mbox);
172 175
173 return 0; 176 return 0;
174} 177}
diff --git a/include/linux/mailbox_client.h b/include/linux/mailbox_client.h
index 307d9cab2026..1726ccbd8009 100644
--- a/include/linux/mailbox_client.h
+++ b/include/linux/mailbox_client.h
@@ -25,6 +25,8 @@ struct mbox_chan;
25 * if the client receives some ACK packet for transmission. 25 * if the client receives some ACK packet for transmission.
26 * Unused if the controller already has TX_Done/RTR IRQ. 26 * Unused if the controller already has TX_Done/RTR IRQ.
27 * @rx_callback: Atomic callback to provide client the data received 27 * @rx_callback: Atomic callback to provide client the data received
28 * @tx_prepare: Atomic callback to ask client to prepare the payload
29 * before initiating the transmission if required.
28 * @tx_done: Atomic callback to tell client of data transmission 30 * @tx_done: Atomic callback to tell client of data transmission
29 */ 31 */
30struct mbox_client { 32struct mbox_client {
@@ -34,6 +36,7 @@ struct mbox_client {
34 bool knows_txdone; 36 bool knows_txdone;
35 37
36 void (*rx_callback)(struct mbox_client *cl, void *mssg); 38 void (*rx_callback)(struct mbox_client *cl, void *mssg);
39 void (*tx_prepare)(struct mbox_client *cl, void *mssg);
37 void (*tx_done)(struct mbox_client *cl, void *mssg, int r); 40 void (*tx_done)(struct mbox_client *cl, void *mssg, int r);
38}; 41};
39 42
diff --git a/include/linux/omap-mailbox.h b/include/linux/omap-mailbox.h
index f8322d9cd235..587bbdd31f5a 100644
--- a/include/linux/omap-mailbox.h
+++ b/include/linux/omap-mailbox.h
@@ -10,20 +10,20 @@
10#define OMAP_MAILBOX_H 10#define OMAP_MAILBOX_H
11 11
12typedef u32 mbox_msg_t; 12typedef u32 mbox_msg_t;
13struct omap_mbox;
14 13
15typedef int __bitwise omap_mbox_irq_t; 14typedef int __bitwise omap_mbox_irq_t;
16#define IRQ_TX ((__force omap_mbox_irq_t) 1) 15#define IRQ_TX ((__force omap_mbox_irq_t) 1)
17#define IRQ_RX ((__force omap_mbox_irq_t) 2) 16#define IRQ_RX ((__force omap_mbox_irq_t) 2)
18 17
19int omap_mbox_msg_send(struct omap_mbox *, mbox_msg_t msg); 18struct mbox_chan;
19struct mbox_client;
20 20
21struct omap_mbox *omap_mbox_get(const char *, struct notifier_block *nb); 21struct mbox_chan *omap_mbox_request_channel(struct mbox_client *cl,
22void omap_mbox_put(struct omap_mbox *mbox, struct notifier_block *nb); 22 const char *chan_name);
23 23
24void omap_mbox_save_ctx(struct omap_mbox *mbox); 24void omap_mbox_save_ctx(struct mbox_chan *chan);
25void omap_mbox_restore_ctx(struct omap_mbox *mbox); 25void omap_mbox_restore_ctx(struct mbox_chan *chan);
26void omap_mbox_enable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq); 26void omap_mbox_enable_irq(struct mbox_chan *chan, omap_mbox_irq_t irq);
27void omap_mbox_disable_irq(struct omap_mbox *mbox, omap_mbox_irq_t irq); 27void omap_mbox_disable_irq(struct mbox_chan *chan, omap_mbox_irq_t irq);
28 28
29#endif /* OMAP_MAILBOX_H */ 29#endif /* OMAP_MAILBOX_H */