0001 ============================
0002 The Common Mailbox Framework
0003 ============================
0004
0005 :Author: Jassi Brar <jaswinder.singh@linaro.org>
0006
0007 This document aims to help developers write client and controller
0008 drivers for the API. But before we start, let us note that the
0009 client (especially) and controller drivers are likely going to be
0010 very platform specific because the remote firmware is likely to be
0011 proprietary and implement non-standard protocol. So even if two
0012 platforms employ, say, PL320 controller, the client drivers can't
0013 be shared across them. Even the PL320 driver might need to accommodate
0014 some platform specific quirks. So the API is meant mainly to avoid
0015 similar copies of code written for each platform. Having said that,
0016 nothing prevents the remote f/w to also be Linux based and use the
0017 same api there. However none of that helps us locally because we only
0018 ever deal at client's protocol level.
0019
0020 Some of the choices made during implementation are the result of this
0021 peculiarity of this "common" framework.
0022
0023
0024
0025 Controller Driver (See include/linux/mailbox_controller.h)
0026 ==========================================================
0027
0028
0029 Allocate mbox_controller and the array of mbox_chan.
0030 Populate mbox_chan_ops, except peek_data() all are mandatory.
0031 The controller driver might know a message has been consumed
0032 by the remote by getting an IRQ or polling some hardware flag
0033 or it can never know (the client knows by way of the protocol).
0034 The method in order of preference is IRQ -> Poll -> None, which
0035 the controller driver should set via 'txdone_irq' or 'txdone_poll'
0036 or neither.
0037
0038
0039 Client Driver (See include/linux/mailbox_client.h)
0040 ==================================================
0041
0042
0043 The client might want to operate in blocking mode (synchronously
0044 send a message through before returning) or non-blocking/async mode (submit
0045 a message and a callback function to the API and return immediately).
0046
0047 ::
0048
0049 struct demo_client {
0050 struct mbox_client cl;
0051 struct mbox_chan *mbox;
0052 struct completion c;
0053 bool async;
0054 /* ... */
0055 };
0056
0057 /*
0058 * This is the handler for data received from remote. The behaviour is purely
0059 * dependent upon the protocol. This is just an example.
0060 */
0061 static void message_from_remote(struct mbox_client *cl, void *mssg)
0062 {
0063 struct demo_client *dc = container_of(cl, struct demo_client, cl);
0064 if (dc->async) {
0065 if (is_an_ack(mssg)) {
0066 /* An ACK to our last sample sent */
0067 return; /* Or do something else here */
0068 } else { /* A new message from remote */
0069 queue_req(mssg);
0070 }
0071 } else {
0072 /* Remote f/w sends only ACK packets on this channel */
0073 return;
0074 }
0075 }
0076
0077 static void sample_sent(struct mbox_client *cl, void *mssg, int r)
0078 {
0079 struct demo_client *dc = container_of(cl, struct demo_client, cl);
0080 complete(&dc->c);
0081 }
0082
0083 static void client_demo(struct platform_device *pdev)
0084 {
0085 struct demo_client *dc_sync, *dc_async;
0086 /* The controller already knows async_pkt and sync_pkt */
0087 struct async_pkt ap;
0088 struct sync_pkt sp;
0089
0090 dc_sync = kzalloc(sizeof(*dc_sync), GFP_KERNEL);
0091 dc_async = kzalloc(sizeof(*dc_async), GFP_KERNEL);
0092
0093 /* Populate non-blocking mode client */
0094 dc_async->cl.dev = &pdev->dev;
0095 dc_async->cl.rx_callback = message_from_remote;
0096 dc_async->cl.tx_done = sample_sent;
0097 dc_async->cl.tx_block = false;
0098 dc_async->cl.tx_tout = 0; /* doesn't matter here */
0099 dc_async->cl.knows_txdone = false; /* depending upon protocol */
0100 dc_async->async = true;
0101 init_completion(&dc_async->c);
0102
0103 /* Populate blocking mode client */
0104 dc_sync->cl.dev = &pdev->dev;
0105 dc_sync->cl.rx_callback = message_from_remote;
0106 dc_sync->cl.tx_done = NULL; /* operate in blocking mode */
0107 dc_sync->cl.tx_block = true;
0108 dc_sync->cl.tx_tout = 500; /* by half a second */
0109 dc_sync->cl.knows_txdone = false; /* depending upon protocol */
0110 dc_sync->async = false;
0111
0112 /* ASync mailbox is listed second in 'mboxes' property */
0113 dc_async->mbox = mbox_request_channel(&dc_async->cl, 1);
0114 /* Populate data packet */
0115 /* ap.xxx = 123; etc */
0116 /* Send async message to remote */
0117 mbox_send_message(dc_async->mbox, &ap);
0118
0119 /* Sync mailbox is listed first in 'mboxes' property */
0120 dc_sync->mbox = mbox_request_channel(&dc_sync->cl, 0);
0121 /* Populate data packet */
0122 /* sp.abc = 123; etc */
0123 /* Send message to remote in blocking mode */
0124 mbox_send_message(dc_sync->mbox, &sp);
0125 /* At this point 'sp' has been sent */
0126
0127 /* Now wait for async chan to be done */
0128 wait_for_completion(&dc_async->c);
0129 }