€•;Œsphinx.addnodes”Œdocument”“”)”}”(Œ rawsource”Œ”Œchildren”]”(Œ translations”Œ LanguagesNode”“”)”}”(hhh]”(hŒ pending_xref”“”)”}”(hhh]”Œdocutils.nodes”ŒText”“”ŒChinese (Simplified)”…””}”(hhŒparent”hubaŒ attributes”}”(Œids”]”Œclasses”]”Œnames”]”Œdupnames”]”Œbackrefs”]”Œ refdomain”Œstd”Œreftype”Œdoc”Œ reftarget”Œ&/translations/zh_CN/driver-api/mailbox”Œmodname”NŒ classname”NŒ refexplicit”ˆuŒtagname”hhh ubh)”}”(hhh]”hŒChinese (Traditional)”…””}”(hhhh2ubah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ&/translations/zh_TW/driver-api/mailbox”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒItalian”…””}”(hhhhFubah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ&/translations/it_IT/driver-api/mailbox”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒJapanese”…””}”(hhhhZubah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ&/translations/ja_JP/driver-api/mailbox”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒKorean”…””}”(hhhhnubah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ&/translations/ko_KR/driver-api/mailbox”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubh)”}”(hhh]”hŒSpanish”…””}”(hhhh‚ubah}”(h]”h ]”h"]”h$]”h&]”Œ refdomain”h)Œreftype”h+Œ reftarget”Œ&/translations/sp_SP/driver-api/mailbox”Œmodname”NŒ classname”NŒ refexplicit”ˆuh1hhh ubeh}”(h]”h ]”h"]”h$]”h&]”Œcurrent_language”ŒEnglish”uh1h hhŒ _document”hŒsource”NŒline”NubhŒsection”“”)”}”(hhh]”(hŒtitle”“”)”}”(hŒThe Common Mailbox Framework”h]”hŒThe Common Mailbox Framework”…””}”(hhªhh¨hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¦hh£hžhhŸŒ@/var/lib/git/docbuild/linux/Documentation/driver-api/mailbox.rst”h KubhŒ field_list”“”)”}”(hhh]”hŒfield”“”)”}”(hhh]”(hŒ field_name”“”)”}”(hŒAuthor”h]”hŒAuthor”…””}”(hhÅhhÃhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1hÁhh¾hŸh¶h KubhŒ field_body”“”)”}”(hŒ(Jassi Brar ”h]”hŒ paragraph”“”)”}”(hŒ'Jassi Brar ”h]”(hŒ Jassi Brar <”…””}”(hŒ Jassi Brar <”hhÙhžhhŸNh NubhŒ reference”“”)”}”(hŒjaswinder.singh@linaro.org”h]”hŒjaswinder.singh@linaro.org”…””}”(hhhhähžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”Œrefuri”Œ!mailto:jaswinder.singh@linaro.org”uh1hâhhÙubhŒ>”…””}”(hŒ>”hhÙhžhhŸNh Nubeh}”(h]”h ]”h"]”h$]”h&]”uh1h×hŸh¶h KhhÓubah}”(h]”h ]”h"]”h$]”h&]”uh1hÑhh¾ubeh}”(h]”h ]”h"]”h$]”h&]”uh1h¼hŸh¶h Khh¹hžhubah}”(h]”h ]”h"]”h$]”h&]”uh1h·hh£hžhhŸh¶h KubhØ)”}”(hXThis document aims to help developers write client and controller drivers for the API. But before we start, let us note that the client (especially) and controller drivers are likely going to be very platform specific because the remote firmware is likely to be proprietary and implement non-standard protocol. So even if two platforms employ, say, PL320 controller, the client drivers can't be shared across them. Even the PL320 driver might need to accommodate some platform specific quirks. So the API is meant mainly to avoid similar copies of code written for each platform. Having said that, nothing prevents the remote f/w to also be Linux based and use the same api there. However none of that helps us locally because we only ever deal at client's protocol level.”h]”hXThis document aims to help developers write client and controller drivers for the API. But before we start, let us note that the client (especially) and controller drivers are likely going to be very platform specific because the remote firmware is likely to be proprietary and implement non-standard protocol. So even if two platforms employ, say, PL320 controller, the client drivers can’t be shared across them. Even the PL320 driver might need to accommodate some platform specific quirks. So the API is meant mainly to avoid similar copies of code written for each platform. Having said that, nothing prevents the remote f/w to also be Linux based and use the same api there. However none of that helps us locally because we only ever deal at client’s protocol level.”…””}”(hjhjhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h×hŸh¶h Khh£hžhubhØ)”}”(hŒmSome of the choices made during implementation are the result of this peculiarity of this "common" framework.”h]”hŒqSome of the choices made during implementation are the result of this peculiarity of this “common†framework.”…””}”(hj!hjhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h×hŸh¶h Khh£hžhubh¢)”}”(hhh]”(h§)”}”(hŒ:Controller Driver (See include/linux/mailbox_controller.h)”h]”hŒ:Controller Driver (See include/linux/mailbox_controller.h)”…””}”(hj2hj0hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¦hj-hžhhŸh¶h KubhØ)”}”(hX¼Allocate mbox_controller and the array of mbox_chan. Populate mbox_chan_ops, except peek_data() all are mandatory. The controller driver might know a message has been consumed by the remote by getting an IRQ or polling some hardware flag or it can never know (the client knows by way of the protocol). The method in order of preference is IRQ -> Poll -> None, which the controller driver should set via 'txdone_irq' or 'txdone_poll' or neither.”h]”hXÄAllocate mbox_controller and the array of mbox_chan. Populate mbox_chan_ops, except peek_data() all are mandatory. The controller driver might know a message has been consumed by the remote by getting an IRQ or polling some hardware flag or it can never know (the client knows by way of the protocol). The method in order of preference is IRQ -> Poll -> None, which the controller driver should set via ‘txdone_irq’ or ‘txdone_poll’ or neither.”…””}”(hj@hj>hžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h×hŸh¶h Khj-hžhubeh}”(h]”Œ8controller-driver-see-include-linux-mailbox-controller-h”ah ]”h"]”Œ:controller driver (see include/linux/mailbox_controller.h)”ah$]”h&]”uh1h¡hh£hžhhŸh¶h Kubh¢)”}”(hhh]”(h§)”}”(hŒ2Client Driver (See include/linux/mailbox_client.h)”h]”hŒ2Client Driver (See include/linux/mailbox_client.h)”…””}”(hjYhjWhžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h¦hjThžhhŸh¶h K(ubhØ)”}”(hŒÒThe client might want to operate in blocking mode (synchronously send a message through before returning) or non-blocking/async mode (submit a message and a callback function to the API and return immediately).”h]”hŒÒThe client might want to operate in blocking mode (synchronously send a message through before returning) or non-blocking/async mode (submit a message and a callback function to the API and return immediately).”…””}”(hjghjehžhhŸNh Nubah}”(h]”h ]”h"]”h$]”h&]”uh1h×hŸh¶h K+hjThžhubhŒ literal_block”“”)”}”(hX… 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); }”h]”hX… 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); }”…””}”(hhhjuubah}”(h]”h ]”h"]”h$]”h&]”Œ xml:space”Œpreserve”uh1jshŸh¶h K1hjThžhubeh}”(h]”Œ0client-driver-see-include-linux-mailbox-client-h”ah ]”h"]”Œ2client driver (see include/linux/mailbox_client.h)”ah$]”h&]”uh1h¡hh£hžhhŸh¶h K(ubeh}”(h]”Œthe-common-mailbox-framework”ah ]”h"]”Œthe common mailbox framework”ah$]”h&]”uh1h¡hhhžhhŸh¶h Kubeh}”(h]”h ]”h"]”h$]”h&]”Œsource”h¶uh1hŒcurrent_source”NŒ current_line”NŒsettings”Œdocutils.frontend”ŒValues”“”)”}”(h¦NŒ generator”NŒ datestamp”NŒ source_link”NŒ source_url”NŒ toc_backlinks”Œentry”Œfootnote_backlinks”KŒ sectnum_xform”KŒstrip_comments”NŒstrip_elements_with_classes”NŒ strip_classes”NŒ report_level”KŒ halt_level”KŒexit_status_level”KŒdebug”NŒwarning_stream”NŒ traceback”ˆŒinput_encoding”Œ utf-8-sig”Œinput_encoding_error_handler”Œstrict”Œoutput_encoding”Œutf-8”Œoutput_encoding_error_handler”j¸Œerror_encoding”ŒUTF-8”Œerror_encoding_error_handler”Œbackslashreplace”Œ language_code”Œen”Œrecord_dependencies”NŒconfig”NŒ id_prefix”hŒauto_id_prefix”Œid”Œ dump_settings”NŒdump_internals”NŒdump_transforms”NŒdump_pseudo_xml”NŒexpose_internals”NŒstrict_visitor”NŒ_disable_config”NŒ_source”h¶Œ _destination”NŒ _config_files”]”Œ7/var/lib/git/docbuild/linux/Documentation/docutils.conf”aŒpep_references”NŒ pep_base_url”Œhttps://peps.python.org/”Œpep_file_url_template”Œpep-%04d”Œrfc_references”NŒ rfc_base_url”Œ&https://datatracker.ietf.org/doc/html/”Œ tab_width”KŒtrim_footnote_reference_space”‰Œfile_insertion_enabled”ˆŒ raw_enabled”KŒline_length_limit”M'Œsyntax_highlight”Œlong”Œ smart_quotes”ˆŒsmartquotes_locales”]”Œcharacter_level_inline_markup”‰Œdoctitle_xform”‰Œ docinfo_xform”KŒsectsubtitle_xform”‰Œ image_loading”Œlink”Œembed_stylesheet”‰Œcloak_email_addresses”ˆŒsection_self_link”‰Œ embed_images”‰Œenv”NubŒreporter”NŒindirect_targets”]”Œsubstitution_defs”}”Œsubstitution_names”}”Œrefnames”}”Œrefids”}”Œnameids”}”(j’jjQjNjŠj‡uŒ nametypes”}”(j’NjQNjŠNuh}”(jh£jNj-j‡jTuŒ footnote_refs”}”Œ citation_refs”}”Œ autofootnotes”]”Œautofootnote_refs”]”Œsymbol_footnotes”]”Œsymbol_footnote_refs”]”Œ footnotes”]”Œ citations”]”Œautofootnote_start”KŒsymbol_footnote_start”KŒ id_counter”Œ collections”ŒCounter”“”}”…”R”Œparse_messages”]”Œtransform_messages”]”Œ transformer”NŒ include_log”]”Œ decoration”Nhžhub.