18c2ecf20Sopenharmony_ci.. SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci
38c2ecf20Sopenharmony_ci==========================
48c2ecf20Sopenharmony_ciMHI (Modem Host Interface)
58c2ecf20Sopenharmony_ci==========================
68c2ecf20Sopenharmony_ci
78c2ecf20Sopenharmony_ciThis document provides information about the MHI protocol.
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ciOverview
108c2ecf20Sopenharmony_ci========
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ciMHI is a protocol developed by Qualcomm Innovation Center, Inc. It is used
138c2ecf20Sopenharmony_ciby the host processors to control and communicate with modem devices over high
148c2ecf20Sopenharmony_cispeed peripheral buses or shared memory. Even though MHI can be easily adapted
158c2ecf20Sopenharmony_cito any peripheral buses, it is primarily used with PCIe based devices. MHI
168c2ecf20Sopenharmony_ciprovides logical channels over the physical buses and allows transporting the
178c2ecf20Sopenharmony_cimodem protocols, such as IP data packets, modem control messages, and
188c2ecf20Sopenharmony_cidiagnostics over at least one of those logical channels. Also, the MHI
198c2ecf20Sopenharmony_ciprotocol provides data acknowledgment feature and manages the power state of the
208c2ecf20Sopenharmony_cimodems via one or more logical channels.
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ciMHI Internals
238c2ecf20Sopenharmony_ci=============
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ciMMIO
268c2ecf20Sopenharmony_ci----
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ciMMIO (Memory mapped IO) consists of a set of registers in the device hardware,
298c2ecf20Sopenharmony_ciwhich are mapped to the host memory space by the peripheral buses like PCIe.
308c2ecf20Sopenharmony_ciFollowing are the major components of MMIO register space:
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ciMHI control registers: Access to MHI configurations registers
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ciMHI BHI registers: BHI (Boot Host Interface) registers are used by the host
358c2ecf20Sopenharmony_cifor downloading the firmware to the device before MHI initialization.
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ciChannel Doorbell array: Channel Doorbell (DB) registers used by the host to
388c2ecf20Sopenharmony_cinotify the device when there is new work to do.
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ciEvent Doorbell array: Associated with event context array, the Event Doorbell
418c2ecf20Sopenharmony_ci(DB) registers are used by the host to notify the device when new events are
428c2ecf20Sopenharmony_ciavailable.
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ciDebug registers: A set of registers and counters used by the device to expose
458c2ecf20Sopenharmony_cidebugging information like performance, functional, and stability to the host.
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ciData structures
488c2ecf20Sopenharmony_ci---------------
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ciAll data structures used by MHI are in the host system memory. Using the
518c2ecf20Sopenharmony_ciphysical interface, the device accesses those data structures. MHI data
528c2ecf20Sopenharmony_cistructures and data buffers in the host system memory regions are mapped for
538c2ecf20Sopenharmony_cithe device.
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ciChannel context array: All channel configurations are organized in channel
568c2ecf20Sopenharmony_cicontext data array.
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ciTransfer rings: Used by the host to schedule work items for a channel. The
598c2ecf20Sopenharmony_citransfer rings are organized as a circular queue of Transfer Descriptors (TD).
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ciEvent context array: All event configurations are organized in the event context
628c2ecf20Sopenharmony_cidata array.
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ciEvent rings: Used by the device to send completion and state transition messages
658c2ecf20Sopenharmony_cito the host
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ciCommand context array: All command configurations are organized in command
688c2ecf20Sopenharmony_cicontext data array.
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ciCommand rings: Used by the host to send MHI commands to the device. The command
718c2ecf20Sopenharmony_cirings are organized as a circular queue of Command Descriptors (CD).
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ciChannels
748c2ecf20Sopenharmony_ci--------
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ciMHI channels are logical, unidirectional data pipes between a host and a device.
778c2ecf20Sopenharmony_ciThe concept of channels in MHI is similar to endpoints in USB. MHI supports up
788c2ecf20Sopenharmony_cito 256 channels. However, specific device implementations may support less than
798c2ecf20Sopenharmony_cithe maximum number of channels allowed.
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ciTwo unidirectional channels with their associated transfer rings form a
828c2ecf20Sopenharmony_cibidirectional data pipe, which can be used by the upper-layer protocols to
838c2ecf20Sopenharmony_citransport application data packets (such as IP packets, modem control messages,
848c2ecf20Sopenharmony_cidiagnostics messages, and so on). Each channel is associated with a single
858c2ecf20Sopenharmony_citransfer ring.
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ciTransfer rings
888c2ecf20Sopenharmony_ci--------------
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ciTransfers between the host and device are organized by channels and defined by
918c2ecf20Sopenharmony_ciTransfer Descriptors (TD). TDs are managed through transfer rings, which are
928c2ecf20Sopenharmony_cidefined for each channel between the device and host and reside in the host
938c2ecf20Sopenharmony_cimemory. TDs consist of one or more ring elements (or transfer blocks)::
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci        [Read Pointer (RP)] ----------->[Ring Element] } TD
968c2ecf20Sopenharmony_ci        [Write Pointer (WP)]-           [Ring Element]
978c2ecf20Sopenharmony_ci                             -          [Ring Element]
988c2ecf20Sopenharmony_ci                              --------->[Ring Element]
998c2ecf20Sopenharmony_ci                                        [Ring Element]
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ciBelow is the basic usage of transfer rings:
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci* Host allocates memory for transfer ring.
1048c2ecf20Sopenharmony_ci* Host sets the base pointer, read pointer, and write pointer in corresponding
1058c2ecf20Sopenharmony_ci  channel context.
1068c2ecf20Sopenharmony_ci* Ring is considered empty when RP == WP.
1078c2ecf20Sopenharmony_ci* Ring is considered full when WP + 1 == RP.
1088c2ecf20Sopenharmony_ci* RP indicates the next element to be serviced by the device.
1098c2ecf20Sopenharmony_ci* When the host has a new buffer to send, it updates the ring element with
1108c2ecf20Sopenharmony_ci  buffer information, increments the WP to the next element and rings the
1118c2ecf20Sopenharmony_ci  associated channel DB.
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_ciEvent rings
1148c2ecf20Sopenharmony_ci-----------
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ciEvents from the device to host are organized in event rings and defined by Event
1178c2ecf20Sopenharmony_ciDescriptors (ED). Event rings are used by the device to report events such as
1188c2ecf20Sopenharmony_cidata transfer completion status, command completion status, and state changes
1198c2ecf20Sopenharmony_cito the host. Event rings are the array of EDs that resides in the host
1208c2ecf20Sopenharmony_cimemory. EDs consist of one or more ring elements (or transfer blocks)::
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_ci        [Read Pointer (RP)] ----------->[Ring Element] } ED
1238c2ecf20Sopenharmony_ci        [Write Pointer (WP)]-           [Ring Element]
1248c2ecf20Sopenharmony_ci                             -          [Ring Element]
1258c2ecf20Sopenharmony_ci                              --------->[Ring Element]
1268c2ecf20Sopenharmony_ci                                        [Ring Element]
1278c2ecf20Sopenharmony_ci
1288c2ecf20Sopenharmony_ciBelow is the basic usage of event rings:
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_ci* Host allocates memory for event ring.
1318c2ecf20Sopenharmony_ci* Host sets the base pointer, read pointer, and write pointer in corresponding
1328c2ecf20Sopenharmony_ci  channel context.
1338c2ecf20Sopenharmony_ci* Both host and device has a local copy of RP, WP.
1348c2ecf20Sopenharmony_ci* Ring is considered empty (no events to service) when WP + 1 == RP.
1358c2ecf20Sopenharmony_ci* Ring is considered full of events when RP == WP.
1368c2ecf20Sopenharmony_ci* When there is a new event the device needs to send, the device updates ED
1378c2ecf20Sopenharmony_ci  pointed by RP, increments the RP to the next element and triggers the
1388c2ecf20Sopenharmony_ci  interrupt.
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_ciRing Element
1418c2ecf20Sopenharmony_ci------------
1428c2ecf20Sopenharmony_ci
1438c2ecf20Sopenharmony_ciA Ring Element is a data structure used to transfer a single block
1448c2ecf20Sopenharmony_ciof data between the host and the device. Transfer ring element types contain a
1458c2ecf20Sopenharmony_cisingle buffer pointer, the size of the buffer, and additional control
1468c2ecf20Sopenharmony_ciinformation. Other ring element types may only contain control and status
1478c2ecf20Sopenharmony_ciinformation. For single buffer operations, a ring descriptor is composed of a
1488c2ecf20Sopenharmony_cisingle element. For large multi-buffer operations (such as scatter and gather),
1498c2ecf20Sopenharmony_cielements can be chained to form a longer descriptor.
1508c2ecf20Sopenharmony_ci
1518c2ecf20Sopenharmony_ciMHI Operations
1528c2ecf20Sopenharmony_ci==============
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_ciMHI States
1558c2ecf20Sopenharmony_ci----------
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ciMHI_STATE_RESET
1588c2ecf20Sopenharmony_ci~~~~~~~~~~~~~~~
1598c2ecf20Sopenharmony_ciMHI is in reset state after power-up or hardware reset. The host is not allowed
1608c2ecf20Sopenharmony_cito access device MMIO register space.
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ciMHI_STATE_READY
1638c2ecf20Sopenharmony_ci~~~~~~~~~~~~~~~
1648c2ecf20Sopenharmony_ciMHI is ready for initialization. The host can start MHI initialization by
1658c2ecf20Sopenharmony_ciprogramming MMIO registers.
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ciMHI_STATE_M0
1688c2ecf20Sopenharmony_ci~~~~~~~~~~~~
1698c2ecf20Sopenharmony_ciMHI is running and operational in the device. The host can start channels by
1708c2ecf20Sopenharmony_ciissuing channel start command.
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_ciMHI_STATE_M1
1738c2ecf20Sopenharmony_ci~~~~~~~~~~~~
1748c2ecf20Sopenharmony_ciMHI operation is suspended by the device. This state is entered when the
1758c2ecf20Sopenharmony_cidevice detects inactivity at the physical interface within a preset time.
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_ciMHI_STATE_M2
1788c2ecf20Sopenharmony_ci~~~~~~~~~~~~
1798c2ecf20Sopenharmony_ciMHI is in low power state. MHI operation is suspended and the device may
1808c2ecf20Sopenharmony_cienter lower power mode.
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_ciMHI_STATE_M3
1838c2ecf20Sopenharmony_ci~~~~~~~~~~~~
1848c2ecf20Sopenharmony_ciMHI operation stopped by the host. This state is entered when the host suspends
1858c2ecf20Sopenharmony_ciMHI operation.
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_ciMHI Initialization
1888c2ecf20Sopenharmony_ci------------------
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_ciAfter system boots, the device is enumerated over the physical interface.
1918c2ecf20Sopenharmony_ciIn the case of PCIe, the device is enumerated and assigned BAR-0 for
1928c2ecf20Sopenharmony_cithe device's MMIO register space. To initialize the MHI in a device,
1938c2ecf20Sopenharmony_cithe host performs the following operations:
1948c2ecf20Sopenharmony_ci
1958c2ecf20Sopenharmony_ci* Allocates the MHI context for event, channel and command arrays.
1968c2ecf20Sopenharmony_ci* Initializes the context array, and prepares interrupts.
1978c2ecf20Sopenharmony_ci* Waits until the device enters READY state.
1988c2ecf20Sopenharmony_ci* Programs MHI MMIO registers and sets device into MHI_M0 state.
1998c2ecf20Sopenharmony_ci* Waits for the device to enter M0 state.
2008c2ecf20Sopenharmony_ci
2018c2ecf20Sopenharmony_ciMHI Data Transfer
2028c2ecf20Sopenharmony_ci-----------------
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_ciMHI data transfer is initiated by the host to transfer data to the device.
2058c2ecf20Sopenharmony_ciFollowing are the sequence of operations performed by the host to transfer
2068c2ecf20Sopenharmony_cidata to device:
2078c2ecf20Sopenharmony_ci
2088c2ecf20Sopenharmony_ci* Host prepares TD with buffer information.
2098c2ecf20Sopenharmony_ci* Host increments the WP of the corresponding channel transfer ring.
2108c2ecf20Sopenharmony_ci* Host rings the channel DB register.
2118c2ecf20Sopenharmony_ci* Device wakes up to process the TD.
2128c2ecf20Sopenharmony_ci* Device generates a completion event for the processed TD by updating ED.
2138c2ecf20Sopenharmony_ci* Device increments the RP of the corresponding event ring.
2148c2ecf20Sopenharmony_ci* Device triggers IRQ to wake up the host.
2158c2ecf20Sopenharmony_ci* Host wakes up and checks the event ring for completion event.
2168c2ecf20Sopenharmony_ci* Host updates the WP of the corresponding event ring to indicate that the
2178c2ecf20Sopenharmony_ci  data transfer has been completed successfully.
2188c2ecf20Sopenharmony_ci
219