On Wed, Oct 30, 2024 at 10:42 AM Jassi Brar <jassisinghbrar@xxxxxxxxx> wrote: > > Hi Anish, > It is the third ping within 10 days, please avoid. Documentation is apologies for this. > not a high priority, esp when it is mostly copying info from header > files. It is true for the api but not true for overall documentation. Reason for writing this document was that I had to read the code to understand how the mailbox driver works. Couple of things this document does is: 1. Explain how the controller, client and hardware are connected 2. Separated out documentation of client, controller and mailbox framework. So, if someone needs to only do a client then they just read that document. 3. Provided example code for controller. 4. In general a better explanation of the framework. > I haven't looked closely and you haven't mentioned in the log what new > info are you adding or clearer? Yes, I should have done that but I added index.rst so thought it is not needed but will do for V2. > From a quick look it seems just api explanation copied into doc > format. Will look closer later. Not completely true. > > Thanks > > On Tue, Oct 29, 2024 at 1:06 PM anish kumar <yesanishhere@xxxxxxxxx> wrote: > > > > Hello Jassi, > > > > Gentle reminder for the review. > > > > On Fri, Oct 25, 2024 at 12:24 PM anish kumar <yesanishhere@xxxxxxxxx> wrote: > > > > > > Hello Jassi, > > > > > > I hope to get some more comments from you before > > > spinning up a new revision. > > > > > > On Thu, Oct 24, 2024 at 8:38 PM Bagas Sanjaya <bagasdotme@xxxxxxxxx> wrote: > > > > > > > > On Sat, Oct 19, 2024 at 12:55:34PM -0700, anish kumar wrote: > > > > > 1. added client documentation > > > > > 2. added controller documentation. > > > > > 3. added framework documentation > > > > > > > > One doc topic on each patch, please. > > > > > > > > > > > > > > Signed-off-by: anish kumar <yesanishhere@xxxxxxxxx> > > > > > --- > > > > > Documentation/driver-api/mailbox/client.rst | 192 ++++++++++++++++++ > > > > > Documentation/driver-api/mailbox/core.rst | 182 +++++++++++++++++ > > > > > Documentation/driver-api/mailbox/index.rst | 45 ++++ > > > > > .../writing_mailbox_controller_drivers.rst | 179 ++++++++++++++++ > > > > > 4 files changed, 598 insertions(+) > > > > > create mode 100644 Documentation/driver-api/mailbox/client.rst > > > > > create mode 100644 Documentation/driver-api/mailbox/core.rst > > > > > create mode 100644 Documentation/driver-api/mailbox/index.rst > > > > > create mode 100644 Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst > > > > > > > > > > diff --git a/Documentation/driver-api/mailbox/client.rst b/Documentation/driver-api/mailbox/client.rst > > > > > new file mode 100644 > > > > > index 000000000000..9088f8373423 > > > > > --- /dev/null > > > > > +++ b/Documentation/driver-api/mailbox/client.rst > > > > > @@ -0,0 +1,192 @@ > > > > > +Mailbox Client Documentation > > > > > +============================ > > > > > + > > > > > +Overview > > > > > +-------- > > > > > +The mailbox client driver is responsible for sending and receiving messages > > > > > +to and from a remote processor. It uses mailbox APIs provided by the > > > > > +mailbox framework. > > > > > + > > > > > +Mailbox Structure > > > > > +----------------- > > > > > +The mailbox structure is defined as follows: > > > > > + > > > > > +.. code-block:: c > > > > > + > > > > > + struct mbox_client { > > > > > + //device associated with the mailbox > > > > > + struct device *dev; > > > > > + // callback for transmission completion > > > > > + void (*tx_done)(struct mbox_client *client); > > > > > + // callback to prepare for sending a message > > > > > + void (*tx_prepare)(struct mbox_client *client); > > > > > + // callback for received messages > > > > > + void (*rx_callback)(struct mbox_client *client, void *data); > > > > > + // flag to indicate if transmission should block > > > > > + bool tx_block; > > > > > + // indicates if the client knows when transmission is done > > > > > + bool knows_txdone; > > > > > + }; > > > > > + > > > > > +Key Functions > > > > > +------------- > > > > > +1. Requesting a Mailbox Channel > > > > > + - **Function**: `mbox_request_channel(struct mbox_client *client, > > > > > + unsigned int channel)` > > > > > + - **Description**: Requests a mailbox channel for sending messages. > > > > > + - **Parameters**: > > > > > + - `client`: Pointer to the mailbox client structure. > > > > > + - `channel`: The specific mailbox channel to request. > > > > > + - **Returns**: A pointer to the mailbox channel on success, or an error > > > > > + code on failure. > > > > > + > > > > > +2. Sending a Message > > > > > + - **Function**: `mbox_send_message(struct mbox_chan *chan, void *msg)` > > > > > + - **Description**: Sends a message through the mailbox channel. > > > > > + - **Parameters**: > > > > > + - `chan`: The mailbox channel used for communication. > > > > > + - `msg`: Pointer to the message to be sent (usually NULL for dummy > > > > > + messages). > > > > > + - **Returns**: 0 on success, or a negative error code on failure. > > > > > + > > > > > +3. Transmitting Completion > > > > > + - **Function**: `mbox_client_txdone(struct mbox_chan *chan, unsigned int > > > > > + msg_id)` > > > > > + - **Description**: Notifies the mailbox framework that message > > > > > + transmission is complete. > > > > > + - **Parameters**: > > > > > + - `chan`: The mailbox channel associated with the message. > > > > > + - `msg_id`: The identifier of the message that was transmitted. > > > > > > > > These functions should've been documented as kernel-doc comments, though. > > > > > > > > > + > > > > > +Usage Example > > > > > +------------- > > > > > +In a typical mailbox client driver, the following steps are typically > > > > > +performed: > > > > > + > > > > > +1. Initialize the Mailbox Client: > > > > > + > > > > > + .. code-block:: c > > > > > + > > > > > + struct mbox_client my_mbox_client = { > > > > > + .dev = &my_device, > > > > > + .tx_done = my_tx_done_callback, > > > > > + .rx_callback = my_rx_callback, > > > > > + .tx_block = false, > > > > > + .knows_txdone = true, > > > > > + }; > > > > > + > > > > > +2. Request a Mailbox Channel: > > > > > + > > > > > + .. code-block:: c > > > > > + > > > > > + mbox_chan = mbox_request_channel(&my_mbox_client, 0); > > > > > + if (IS_ERR(mbox_chan)) { > > > > > + // Handle error > > > > > + } > > > > > + > > > > > +3. Send a Message: > > > > > + > > > > > + .. code-block:: c > > > > > + > > > > > + int ret = mbox_send_message(mbox_chan, NULL); // Sending a dummy message > > > > > + if (ret < 0) { > > > > > + // Handle error > > > > > + } > > > > > + > > > > > +4. Complete Transmission: > > > > > + > > > > > + .. code-block:: c > > > > > + > > > > > + mbox_client_txdone(mbox_chan, 0); > > > > > + > > > > > +Interrupt Handling > > > > > +------------------ > > > > > +The mailbox interface can trigger interrupts upon message receipt. Handlers > > > > > +should be implemented in the `rx_callback` function defined in the mailbox > > > > > +client structure to process incoming messages. > > > > > + > > > > > +Example Mailbox Client Driver > > > > > +----------------------------- > > > > > +.. code-block:: c > > > > > + > > > > > + struct demo_client { > > > > > + struct mbox_client cl; > > > > > + struct mbox_chan *mbox; > > > > > + struct completion c; > > > > > + bool async; > > > > > + /* ... */ > > > > > + }; > > > > > + > > > > > + /* > > > > > + * This is the handler for data received from remote. The behaviour is purely > > > > > + * dependent upon the protocol. This is just an example. > > > > > + */ > > > > > + static void message_from_remote(struct mbox_client *cl, void *mssg) > > > > > + { > > > > > + struct demo_client *dc = container_of(cl, struct demo_client, cl); > > > > > + if (dc->async) { > > > > > + if (is_an_ack(mssg)) { > > > > > + /* An ACK to our last sample sent */ > > > > > + return; /* Or do something else here */ > > > > > + } else { /* A new message from remote */ > > > > > + queue_req(mssg); > > > > > + } > > > > > + } else { > > > > > + /* Remote f/w sends only ACK packets on this channel */ > > > > > + return; > > > > > + } > > > > > + } > > > > > + > > > > > + static void sample_sent(struct mbox_client *cl, void *mssg, int r) > > > > > + { > > > > > + struct demo_client *dc = container_of(cl, struct demo_client, cl); > > > > > + complete(&dc->c); > > > > > + } > > > > > + > > > > > + static void client_demo(struct platform_device *pdev) > > > > > + { > > > > > + struct demo_client *dc_sync, *dc_async; > > > > > + /* The controller already knows async_pkt and sync_pkt */ > > > > > + struct async_pkt ap; > > > > > + struct sync_pkt sp; > > > > > + > > > > > + dc_sync = kzalloc(sizeof(*dc_sync), GFP_KERNEL); > > > > > + dc_async = kzalloc(sizeof(*dc_async), GFP_KERNEL); > > > > > + > > > > > + /* Populate non-blocking mode client */ > > > > > + dc_async->cl.dev = &pdev->dev; > > > > > + dc_async->cl.rx_callback = message_from_remote; > > > > > + dc_async->cl.tx_done = sample_sent; > > > > > + dc_async->cl.tx_block = false; > > > > > + dc_async->cl.tx_tout = 0; /* doesn't matter here */ > > > > > + dc_async->cl.knows_txdone = false; /* depending upon protocol */ > > > > > + dc_async->async = true; > > > > > + init_completion(&dc_async->c); > > > > > + > > > > > + /* Populate blocking mode client */ > > > > > + dc_sync->cl.dev = &pdev->dev; > > > > > + dc_sync->cl.rx_callback = message_from_remote; > > > > > + dc_sync->cl.tx_done = NULL; /* operate in blocking mode */ > > > > > + dc_sync->cl.tx_block = true; > > > > > + dc_sync->cl.tx_tout = 500; /* by half a second */ > > > > > + dc_sync->cl.knows_txdone = false; /* depending upon protocol */ > > > > > + dc_sync->async = false; > > > > > + > > > > > + /* ASync mailbox is listed second in 'mboxes' property */ > > > > > + dc_async->mbox = mbox_request_channel(&dc_async->cl, 1); > > > > > + /* Populate data packet */ > > > > > + /* ap.xxx = 123; etc */ > > > > > + /* Send async message to remote */ > > > > > + mbox_send_message(dc_async->mbox, &ap); > > > > > + > > > > > + /* Sync mailbox is listed first in 'mboxes' property */ > > > > > + dc_sync->mbox = mbox_request_channel(&dc_sync->cl, 0); > > > > > + /* Populate data packet */ > > > > > + /* sp.abc = 123; etc */ > > > > > + /* Send message to remote in blocking mode */ > > > > > + mbox_send_message(dc_sync->mbox, &sp); > > > > > + /* At this point 'sp' has been sent */ > > > > > + > > > > > + /* Now wait for async chan to be done */ > > > > > + wait_for_completion(&dc_async->c); > > > > > + } > > > > > diff --git a/Documentation/driver-api/mailbox/core.rst b/Documentation/driver-api/mailbox/core.rst > > > > > new file mode 100644 > > > > > index 000000000000..d1220086da67 > > > > > --- /dev/null > > > > > +++ b/Documentation/driver-api/mailbox/core.rst > > > > > @@ -0,0 +1,182 @@ > > > > > +===================== > > > > > +mailbox documentation > > > > > +===================== > > > > > + > > > > > +Hardware Introduction > > > > > +===================== > > > > > + > > > > > +Mailbox hardware is a specialized component found in multi-core > > > > > +processors and embedded systems that facilitates inter-processor > > > > > +communication (IPC) or communication between different hardware > > > > > +components. It provides a structured mechanism for sending and > > > > > +receiving messages, allowing various processors or devices to > > > > > +exchange data efficiently. Here's an overview of its key > > > > > +characteristics and functions: > > > > > + > > > > > +Key Characteristics of Mailbox Hardware > > > > > +Interrupt Handling: Many mailbox implementations support > > > > > +interrupt-driven communication. This allows a receiving processor > > > > > +to be alerted when a new message arrives, facilitating immediate > > > > > +processing without polling the mailbox constantly. > > > > > + > > > > > +Hardware Registers: Mailbox hardware often includes registers for > > > > > +configuration and status monitoring. These registers can be used > > > > > +to control the mailbox's behavior, check for available messages, > > > > > +or acknowledge message receipt. > > > > > + > > > > > +Support for Multiple Protocols: Mailboxes can support various > > > > > +communication protocols, enabling interoperability between different > > > > > +hardware components and simplifying the integration of diverse systems. > > > > > + > > > > > +Synchronous and Asynchronous Modes: Mailbox hardware can operate in > > > > > +both synchronous and asynchronous modes. In synchronous mode, the > > > > > +sender may wait for the receiver to acknowledge receipt before > > > > > +proceeding, while in asynchronous mode, the sender can continue > > > > > +executing other tasks immediately after sending the message. > > > > > + > > > > > + > > > > > +Mailbox framework design > > > > > +======================== > > > > > + > > > > > +The mailbox facilitates interprocessor communication by allowing processors to > > > > > +exchange messages or signals. The mailbox framework consists of: > > > > > + > > > > > +Mailbox Controller: This is platform-specific and is responsible for configuring > > > > > +and managing interrupts from the remote processor. It offers a generic API for > > > > > +the mailbox client. > > > > > + > > > > > +Mailbox Client: This component handles the sending and receiving of messages. > > > > > + > > > > > + > > > > > +............................................................................ > > > > > +: client driver client_a client_b : > > > > > +............................................................................ > > > > > + ^-------------------^ > > > > > + | > > > > > + | > > > > > +............................................................................ > > > > > +: controller framework mailbox : > > > > > +....................................|....................................... > > > > > + | > > > > > + | > > > > > +............................................................................ > > > > > +: controller driver device specific : > > > > > +....................................|....................................... > > > > > + | > > > > > + | > > > > > +kernel | > > > > > +............................................................................ > > > > > +hardware | > > > > > + | > > > > > + | > > > > > +............................................................................ > > > > > +: remote processor : > > > > > +............................................................................ > > > > > > > > htmldocs build errors out: > > > > > > > > Documentation/driver-api/mailbox/core.rst:57: WARNING: Block quote ends without a blank line; unexpected unindent. > > > > Documentation/driver-api/mailbox/core.rst:57: CRITICAL: Missing matching underline for section title overline. > > > > > > > > ............................................................................ > > > > : controller framework mailbox : > > > > ....................................|....................................... > > > > > > > > reST markup error: > > > > Documentation/driver-api/mailbox/core.rst:57: (SEVERE/4) Missing matching underline for section title overline. > > > > > > > > ............................................................................ > > > > : controller framework mailbox : > > > > ....................................|....................................... > > > > > > > > I have to fix up the design diagram and wrap it: > > > > > > > > ---- >8 ---- > > > > diff --git a/Documentation/driver-api/mailbox/core.rst b/Documentation/driver-api/mailbox/core.rst > > > > index d1220086da679f..8d56d81007c11c 100644 > > > > --- a/Documentation/driver-api/mailbox/core.rst > > > > +++ b/Documentation/driver-api/mailbox/core.rst > > > > @@ -47,31 +47,32 @@ the mailbox client. > > > > > > > > Mailbox Client: This component handles the sending and receiving of messages. > > > > > > > > +:: > > > > > > > > -............................................................................ > > > > -: client driver client_a client_b : > > > > -............................................................................ > > > > - ^-------------------^ > > > > - | > > > > - | > > > > -............................................................................ > > > > -: controller framework mailbox : > > > > -....................................|....................................... > > > > - | > > > > - | > > > > -............................................................................ > > > > -: controller driver device specific : > > > > -....................................|....................................... > > > > - | > > > > - | > > > > -kernel | > > > > -............................................................................ > > > > -hardware | > > > > - | > > > > - | > > > > -............................................................................ > > > > -: remote processor : > > > > -............................................................................ > > > > + +---------------------------------------------------------------------------+ > > > > + | client driver client_a client_b | > > > > + +---------------------------------------------------------------------------+ > > > > + ^-------------------^ > > > > + | > > > > + | > > > > + +--------------------------------------------------------------------------+ > > > > + | controller framework mailbox | > > > > + +-----------------------------------|--------------------------------------+ > > > > + | > > > > + | > > > > + +--------------------------------------------------------------------------+ > > > > + | controller driver device specific | > > > > + +-----------------------------------|--------------------------------------+ > > > > + | > > > > + | > > > > + kernel | > > > > + ---------------------------------------------------------------------------- > > > > + hardware | > > > > + | > > > > + | > > > > + +--------------------------------------------------------------------------+ > > > > + | remote processor | > > > > + +--------------------------------------------------------------------------+ > > > > > > > > > > > > In the context of a mailbox framework, a channel refers to a dedicated > > > > > > > > > + > > > > > + > > > > > +In the context of a mailbox framework, a channel refers to a dedicated > > > > > +communication pathway between two or more processors or components. By using > > > > > +channels, the framework abstracts the complexity of interprocessor communication. > > > > > + > > > > > +Data Structures > > > > > +================ > > > > > + > > > > > +- **struct mbox_client** > > > > > + This structure represents a client that communicates over a mailbox > > > > > + channel. It holds information such as: > > > > > + - A pointer to the device associated with the client (`dev`). > > > > > + - Callback functions for handling message transmission events, including: > > > > > + - `rx_callback`: Called when a message is received. > > > > > + - `tx_done`: Called when a message transmission is acknowledged. > > > > > + - Flags that specify the client’s configuration, such as whether it operates > > > > > + in blocking mode. > > > > > + > > > > > +- **struct mbox_chan** > > > > > + This structure represents an individual mailbox channel. It maintains the > > > > > + state required for message queuing and transmission. Key members include: > > > > > + - `msg_data`: Array of messages queued for transmission. > > > > > + - `msg_count`: Number of messages currently queued. > > > > > + - `msg_free`: Index of the next free slot in the message queue. > > > > > + - `active_req`: Pointer to the currently active message being transmitted. > > > > > + - Synchronization primitives to manage access from multiple contexts. > > > > > + > > > > > +- **struct mbox_controller** > > > > > + This structure represents a mailbox controller that manages multiple > > > > > + channels. It includes: > > > > > + - A pointer to the device managing the mailbox. > > > > > + - Operations for sending and receiving messages, as well as initializing > > > > > + and shutting down the mailbox. > > > > > + - A list of associated channels and the total number of channels available. > > > > > > > > Shouldn't these structs be documented as kernel-doc comments? tl;dr: > > > > see Documentation/doc-guide/kernel-doc.html > > > > > > > > > + > > > > > +controller framework APIs > > > > > +========================= > > > > > + > > > > > +``struct `mbox_controller` Initialization > > > > > +----------------------------------------- > > > > > > > > Properly double-backquote the struct name to format it as inline code: > > > > > > > > ---- >8 ---- > > > > diff --git a/Documentation/driver-api/mailbox/core.rst b/Documentation/driver-api/mailbox/core.rst > > > > index 239538f497e41a..d83456164464aa 100644 > > > > --- a/Documentation/driver-api/mailbox/core.rst > > > > +++ b/Documentation/driver-api/mailbox/core.rst > > > > @@ -117,7 +117,7 @@ Data Structures > > > > controller framework APIs > > > > ========================= > > > > > > > > -``struct `mbox_controller` Initialization > > > > +``struct mbox_controller`` Initialization > > > > ----------------------------------------- > > > > > > > > Just like any other kernel framework, the whole mailbox controller registration > > > > > > > > > + > > > > > +Just like any other kernel framework, the whole mailbox controller registration > > > > > +relies on the driver filling a structure and registering against the > > > > > +framework. In our case, that structure is mbox_controller. > > > > > + > > > > > +The first thing you need to do in your driver is to allocate this > > > > > +structure. Any of the usual memory allocators will do, but you'll also > > > > > +need to initialize a few fields in there: > > > > > + > > > > > +- ``dev``: should hold the pointer to the ``struct device`` associated > > > > > + to your current driver instance. > > > > > + > > > > > +- ``ops``: Operators that work on each communication channel. > > > > > + > > > > > +- ``chans``: Array of channels. > > > > > + > > > > > +- ``num_chans``: Number of channels in the `chans` array. > > > > > + > > > > > +- ``txdone_irq``: Indicates if the controller can report to the API > > > > > + when the last transmitted data was read by the > > > > > + remote (e.g., if it has a TX ACK interrupt). > > > > > + > > > > > +All the below fields are not mandatory. > > > > > + > > > > > +- ``txdone_poll``: Indicates if the controller can read but not report > > > > > + the TX done. For example, some register may show > > > > > + the TX status, but no interrupt is raised. This > > > > > + field is ignored if `txdone_irq` is set. > > > > > + > > > > > +- ``txpoll_period``: If `txdone_poll` is in effect, the API polls for > > > > > + the last TX status after this many milliseconds. > > > > > + > > > > > +- ``of_xlate``: Controller driver-specific mapping of channel via > > > > > + Device Tree (DT). > > > > > + > > > > > + > > > > > +Key Functions > > > > > +------------- > > > > > + > > > > > +- **int devm_mbox_controller_register(struct mbox_controller *mbox)** > > > > > + This function registers a mailbox controller with the kernel. It makes the > > > > > + channels associated with the controller available for client requests. The > > > > > + function performs sanity checks on the controller structure to ensure all > > > > > + necessary fields are populated. > > > > > + > > > > > +- **struct mbox_chan *mbox_request_channel(struct mbox_client *cl, int index)** > > > > > + This function requests a mailbox channel for a specified client, identified > > > > > + by an index. It searches for the appropriate mailbox channel, and if found, > > > > > + it returns a pointer to the channel. If the request fails (e.g., if the > > > > > + index is invalid), it returns an error pointer. > > > > > + > > > > > +- **void mbox_free_channel(struct mbox_chan *chan)** > > > > > + This function releases a mailbox channel that was previously allocated for a > > > > > + client. It ensures that the channel can be reused by other clients. If any > > > > > + messages are still in the queue, they are aborted, and no callbacks are made. > > > > > + > > > > > +- **int mbox_send_message(struct mbox_chan *chan, void *mssg)** > > > > > + This function is used by clients to send a message through the specified > > > > > + mailbox channel. The function can operate in either blocking or non-blocking > > > > > + mode, depending on the client’s configuration. It will queue the message for > > > > > + transmission and notify the client once the message is acknowledged. > > > > > + > > > > > +- **void mbox_chan_received_data(struct mbox_chan *chan, void *mssg)** > > > > > + This function is called by the controller driver to notify the mailbox > > > > > + framework that a message has been received on the specified channel. The > > > > > + received message is then passed to the appropriate client's `rx_callback` > > > > > + function for processing. > > > > > > > > Shouldn't these functions also be documented as kernel-doc comments? > > > > > > > > > diff --git a/Documentation/driver-api/mailbox/index.rst b/Documentation/driver-api/mailbox/index.rst > > > > > new file mode 100644 > > > > > index 000000000000..e254a8fdb66a > > > > > --- /dev/null > > > > > +++ b/Documentation/driver-api/mailbox/index.rst > > > > > @@ -0,0 +1,45 @@ > > > > > +======================= > > > > > +Mailbox documentation > > > > > +======================= > > > > > + > > > > > +Mailbox documentation provides documents for various aspects of mailbox > > > > > +framework. > > > > > + > > > > > +Mailbox development documentation > > > > > +--------------------------------- > > > > > + > > > > > +This book helps with mailbox internal APIs and guide for mailbox device > > > > > +driver writers. > > > > > + > > > > > +.. toctree:: > > > > > + :maxdepth: 1 > > > > > + > > > > > + core > > > > > + > > > > > +mailbox controller driver documentation > > > > > +------------------------------ > > > > > + > > > > > +This book is a guide to device driver writers on how to register > > > > > +mailbox controller to the mailbox framework. > > > > > + > > > > > +.. toctree:: > > > > > + :maxdepth: 1 > > > > > + > > > > > + writing_mailbox_controller_drivers > > > > > + > > > > > +mailbox client driver documentation > > > > > +------------------------------ > > > > > > > > Match up section underline length by its title: > > > > > > > > ---- >8 ---- > > > > diff --git a/Documentation/driver-api/mailbox/index.rst b/Documentation/driver-api/mailbox/index.rst > > > > index e254a8fdb66ac7..02d7d5e8660999 100644 > > > > --- a/Documentation/driver-api/mailbox/index.rst > > > > +++ b/Documentation/driver-api/mailbox/index.rst > > > > @@ -1,6 +1,6 @@ > > > > -======================= > > > > +===================== > > > > Mailbox documentation > > > > -======================= > > > > +===================== > > > > > > > > Mailbox documentation provides documents for various aspects of mailbox > > > > framework. > > > > @@ -17,7 +17,7 @@ driver writers. > > > > core > > > > > > > > mailbox controller driver documentation > > > > ------------------------------- > > > > +--------------------------------------- > > > > > > > > This book is a guide to device driver writers on how to register > > > > mailbox controller to the mailbox framework. > > > > @@ -28,7 +28,7 @@ mailbox controller to the mailbox framework. > > > > writing_mailbox_controller_drivers > > > > > > > > mailbox client driver documentation > > > > ------------------------------- > > > > +----------------------------------- > > > > > > > > This book is a guide to mailbox client driver writers. > > > > > > > > > > > > > + > > > > > +This book is a guide to mailbox client driver writers. > > > > > + > > > > > +.. toctree:: > > > > > + :maxdepth: 1 > > > > > + > > > > > + client > > > > > + > > > > > +.. only:: subproject and html > > > > > + > > > > > + Indices > > > > > + ======= > > > > > + > > > > > + * :ref:`genindex` > > > > > > > > Fix up also the reference link on parent toctree: > > > > > > > > ---- >8 ---- > > > > diff --git a/Documentation/driver-api/index.rst b/Documentation/driver-api/index.rst > > > > index 7f83e05769b4a4..b4d78b92fd921a 100644 > > > > --- a/Documentation/driver-api/index.rst > > > > +++ b/Documentation/driver-api/index.rst > > > > @@ -102,7 +102,7 @@ Subsystem-specific APIs > > > > ipmb > > > > ipmi > > > > libata > > > > - mailbox > > > > + mailbox/index > > > > md/index > > > > media/index > > > > mei/index > > > > > > > > > diff --git a/Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst b/Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst > > > > > new file mode 100644 > > > > > index 000000000000..2a82645c1357 > > > > > --- /dev/null > > > > > +++ b/Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst > > > > > @@ -0,0 +1,179 @@ > > > > > +.. SPDX-License-Identifier: GPL-2.0 > > > > > + > > > > > +.. _writing_mailbox_controller_drivers: > > > > > + > > > > > +================================== > > > > > +Writing Mailbox Controller Drivers > > > > > +================================== > > > > > + > > > > > +Introduction > > > > > +============ > > > > > + > > > > > +This document serves as a basic guideline for driver programmers that need > > > > > +to hack a new mailbox controller driver or understand the essentials of > > > > > +the existing ones. > > > > > + > > > > > +Driver Boilerplate > > > > > +================== > > > > > + > > > > > +As a bare minimum, a mailbox controller driver needs to call > > > > > +``mbox_controller_register`` function to register with the framework. > > > > > + > > > > > +A basic driver skeleton could look like this for a mailbox hardware that > > > > > +has the following characteristics: > > > > > +a. It supports only a single channel, i.e., only the remote processor can > > > > > + send interrupts. > > > > > +b. Data transfer is over the registers associated with mailbox hardware. > > > > > +c. Mailbox hardware is configured to receive interrupts. > > > > > +d. When the remote processor is ready to send data, it triggers a mailbox > > > > > + interrupt. > > > > > +e. As part of interrupt handling by Linux, it copies data from the registers. > > > > > + > > > > > +.. code-block:: c > > > > > + > > > > > + #include <linux/device.h> > > > > > + #include <linux/interrupt.h> > > > > > + #include <linux/io.h> > > > > > + #include <linux/kernel.h> > > > > > + #include <linux/mailbox_controller.h> > > > > > + #include <linux/module.h> > > > > > + #include <linux/of.h> > > > > > + #include <linux/platform_device.h> > > > > > + #define DRIVER_NAME "dummy_controller" > > > > > + > > > > > + struct dummy_mbox { > > > > > + struct device *dev; > > > > > + struct mbox_controller controller; > > > > > + int irq; > > > > > + }; > > > > > + > > > > > + static void dummy_mbox_receive(struct mbox_chan *chan) > > > > > + { > > > > > + struct dummy_mbox *mbox = chan->con_priv; > > > > > + int val; > > > > > + > > > > > + // Data copied from registers > > > > > + val = read_register(); > > > > > + mbox_chan_received_data(chan, &val); > > > > > + } > > > > > + > > > > > + static irqreturn_t dummy_mbox_irq_handler(int irq, void *data) > > > > > + { > > > > > + struct mbox_chan *chan = data; > > > > > + struct dummy_mbox *mbox = chan->con_priv; > > > > > + u32 reg; > > > > > + > > > > > + // Read registers to see if data is received > > > > > + dummy_mbox_receive(chan); > > > > > + mbox_chan_txdone(chan, 0); > > > > > + return reg ? IRQ_HANDLED : IRQ_NONE; > > > > > + } > > > > > + > > > > > + static int dummy_mbox_send_data(struct mbox_chan *chan, void *data) > > > > > + { > > > > > + // Write data in registers to send it to the remote processor > > > > > + return 0; > > > > > + } > > > > > + > > > > > + static int dummy_mbox_startup(struct mbox_chan *chan) > > > > > + { > > > > > + struct dummy_mbox *mbox = chan->con_priv; > > > > > + u32 reg; > > > > > + int ret; > > > > > + > > > > > + ret = devm_request_irq(mbox->dev, mbox->irq, dummy_mbox_irq_handler, 0, > > > > > + DRIVER_NAME, chan); > > > > > + if (ret < 0) { > > > > > + dev_err(mbox->dev, "Cannot request irq\n"); > > > > > + return ret; > > > > > + } > > > > > + > > > > > + /* Register write to enable IRQ generation */ > > > > > + > > > > > + return 0; > > > > > + } > > > > > + > > > > > + static void dummy_mbox_shutdown(struct mbox_chan *chan) > > > > > + { > > > > > + struct dummy_mbox *mbox = chan->con_priv; > > > > > + > > > > > + /* Disable interrupt generation */ > > > > > + devm_free_irq(mbox->dev, mbox->irq, chan); > > > > > + } > > > > > + > > > > > + static const struct mbox_chan_ops dummy_mbox_ops = { > > > > > + .send_data = dummy_mbox_send_data, > > > > > + .startup = dummy_mbox_startup, > > > > > + .shutdown = dummy_mbox_shutdown, > > > > > + }; > > > > > + > > > > > + static int dummy_mbox_probe(struct platform_device *pdev) > > > > > + { > > > > > + struct dummy_mbox *mbox; > > > > > + struct mbox_chan *chans; > > > > > + int ret; > > > > > + > > > > > + mbox = devm_kzalloc(&pdev->dev, sizeof(*mbox), GFP_KERNEL); > > > > > + if (!mbox) > > > > > + return -ENOMEM; > > > > > + > > > > > + /* Allocate one channel */ > > > > > + chans = devm_kzalloc(&pdev->dev, sizeof(*chans), GFP_KERNEL); > > > > > + if (!chans) > > > > > + return -ENOMEM; > > > > > + > > > > > + mbox->base = devm_platform_ioremap_resource(pdev, 0); > > > > > + if (IS_ERR(mbox->base)) > > > > > + return PTR_ERR(mbox->base); > > > > > + > > > > > + mbox->irq = platform_get_irq(pdev, 0); > > > > > + if (mbox->irq < 0) > > > > > + return mbox->irq; > > > > > + > > > > > + mbox->dev = &pdev->dev; > > > > > + > > > > > + /* Hardware supports only one channel. */ > > > > > + mbox->controller.dev = mbox->dev; > > > > > + mbox->controller.num_chans = 1; > > > > > + mbox->controller.chans = chans; > > > > > + mbox->controller.ops = &dummy_mbox_ops; > > > > > + mbox->controller.txdone_irq = true; > > > > > + > > > > > + ret = devm_mbox_controller_register(mbox->dev, &mbox->controller); > > > > > + if (ret) { > > > > > + dev_err(&pdev->dev, "Could not register mailbox controller\n"); > > > > > + return ret; > > > > > + } > > > > > + > > > > > + return ret; > > > > > + } > > > > > + > > > > > + static const struct of_device_id dummy_mbox_match[] = { > > > > > + { .compatible = "dummy,dummy-mailbox" }, > > > > > + { }, > > > > > + }; > > > > > + > > > > > + MODULE_DEVICE_TABLE(of, dummy_mbox_match); > > > > > + > > > > > + static struct platform_driver dummy_mbox_driver = { > > > > > + .probe = dummy_mbox_probe, > > > > > + .driver = { > > > > > + .name = DRIVER_NAME, > > > > > + .of_match_table = dummy_mbox_match, > > > > > + }, > > > > > + }; > > > > > + > > > > > + module_platform_driver(dummy_mbox_driver); > > > > > + MODULE_LICENSE("GPL v2"); > > > > > + MODULE_DESCRIPTION("Dummy mailbox controller driver"); > > > > > + > > > > > +In the above code, a couple of things are done: > > > > > +a. The controller is registered in the probe along with callbacks, which in > > > > > + this case are the bare minimum: ``startup``, ``shutdown``, and > > > > > + ``send_data``. > > > > > +b. IRQ is registered to get notifications from the remote processor. > > > > > +c. In the IRQ handler, registers are read to copy data, and > > > > > + ``mbox_chan_received_data`` is called to hand over the data to the client. > > > > > +d. ``mbox_chan_txdone`` is called to let the framework know that this data > > > > > + is the last data and no more data is to be expected for the current transfer. > > > > > + > > > > > > > > Sphinx warns out numerous indentation warnings on the lists, so I have to > > > > fix them up: > > > > > > > > ---- >8 ---- > > > > diff --git a/Documentation/driver-api/mailbox/client.rst b/Documentation/driver-api/mailbox/client.rst > > > > index 9088f83734230d..17dafaca056777 100644 > > > > --- a/Documentation/driver-api/mailbox/client.rst > > > > +++ b/Documentation/driver-api/mailbox/client.rst > > > > @@ -31,6 +31,7 @@ The mailbox structure is defined as follows: > > > > Key Functions > > > > ------------- > > > > 1. Requesting a Mailbox Channel > > > > + > > > > - **Function**: `mbox_request_channel(struct mbox_client *client, > > > > unsigned int channel)` > > > > - **Description**: Requests a mailbox channel for sending messages. > > > > @@ -41,15 +42,19 @@ Key Functions > > > > code on failure. > > > > > > > > 2. Sending a Message > > > > + > > > > - **Function**: `mbox_send_message(struct mbox_chan *chan, void *msg)` > > > > - **Description**: Sends a message through the mailbox channel. > > > > - **Parameters**: > > > > + > > > > - `chan`: The mailbox channel used for communication. > > > > - `msg`: Pointer to the message to be sent (usually NULL for dummy > > > > messages). > > > > + > > > > - **Returns**: 0 on success, or a negative error code on failure. > > > > > > > > 3. Transmitting Completion > > > > + > > > > - **Function**: `mbox_client_txdone(struct mbox_chan *chan, unsigned int > > > > msg_id)` > > > > - **Description**: Notifies the mailbox framework that message > > > > diff --git a/Documentation/driver-api/mailbox/core.rst b/Documentation/driver-api/mailbox/core.rst > > > > index 8d56d81007c11c..239538f497e41a 100644 > > > > --- a/Documentation/driver-api/mailbox/core.rst > > > > +++ b/Documentation/driver-api/mailbox/core.rst > > > > @@ -85,16 +85,20 @@ Data Structures > > > > - **struct mbox_client** > > > > This structure represents a client that communicates over a mailbox > > > > channel. It holds information such as: > > > > + > > > > - A pointer to the device associated with the client (`dev`). > > > > - Callback functions for handling message transmission events, including: > > > > + > > > > - `rx_callback`: Called when a message is received. > > > > - `tx_done`: Called when a message transmission is acknowledged. > > > > + > > > > - Flags that specify the client’s configuration, such as whether it operates > > > > in blocking mode. > > > > > > > > - **struct mbox_chan** > > > > This structure represents an individual mailbox channel. It maintains the > > > > state required for message queuing and transmission. Key members include: > > > > + > > > > - `msg_data`: Array of messages queued for transmission. > > > > - `msg_count`: Number of messages currently queued. > > > > - `msg_free`: Index of the next free slot in the message queue. > > > > @@ -104,6 +108,7 @@ Data Structures > > > > - **struct mbox_controller** > > > > This structure represents a mailbox controller that manages multiple > > > > channels. It includes: > > > > + > > > > - A pointer to the device managing the mailbox. > > > > - Operations for sending and receiving messages, as well as initializing > > > > and shutting down the mailbox. > > > > @@ -133,21 +138,20 @@ need to initialize a few fields in there: > > > > - ``num_chans``: Number of channels in the `chans` array. > > > > > > > > - ``txdone_irq``: Indicates if the controller can report to the API > > > > - when the last transmitted data was read by the > > > > - remote (e.g., if it has a TX ACK interrupt). > > > > + when the last transmitted data was read by the remote (e.g., if it has a > > > > + TX ACK interrupt). > > > > > > > > All the below fields are not mandatory. > > > > > > > > - ``txdone_poll``: Indicates if the controller can read but not report > > > > - the TX done. For example, some register may show > > > > - the TX status, but no interrupt is raised. This > > > > - field is ignored if `txdone_irq` is set. > > > > + the TX done. For example, some register may show the TX status, but no > > > > + interrupt is raised. This field is ignored if `txdone_irq` is set. > > > > > > > > - ``txpoll_period``: If `txdone_poll` is in effect, the API polls for > > > > - the last TX status after this many milliseconds. > > > > + the last TX status after this many milliseconds. > > > > > > > > - ``of_xlate``: Controller driver-specific mapping of channel via > > > > - Device Tree (DT). > > > > + Device Tree (DT). > > > > > > > > > > > > Key Functions > > > > diff --git a/Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst b/Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst > > > > index 2a82645c13573e..853adf6918173d 100644 > > > > --- a/Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst > > > > +++ b/Documentation/driver-api/mailbox/writing_mailbox_controller_drivers.rst > > > > @@ -21,6 +21,7 @@ As a bare minimum, a mailbox controller driver needs to call > > > > > > > > A basic driver skeleton could look like this for a mailbox hardware that > > > > has the following characteristics: > > > > + > > > > a. It supports only a single channel, i.e., only the remote processor can > > > > send interrupts. > > > > b. Data transfer is over the registers associated with mailbox hardware. > > > > @@ -168,6 +169,7 @@ e. As part of interrupt handling by Linux, it copies data from the registers. > > > > MODULE_DESCRIPTION("Dummy mailbox controller driver"); > > > > > > > > In the above code, a couple of things are done: > > > > + > > > > a. The controller is registered in the probe along with callbacks, which in > > > > this case are the bare minimum: ``startup``, ``shutdown``, and > > > > ``send_data``. > > > > > > > > Thanks. > > > > > > > > -- > > > > An old man doll... just what I always wanted! - Clara