162306a36Sopenharmony_ci.. SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci
362306a36Sopenharmony_ci==========================
462306a36Sopenharmony_ciMHI (Modem Host Interface)
562306a36Sopenharmony_ci==========================
662306a36Sopenharmony_ci
762306a36Sopenharmony_ciThis document provides information about the MHI protocol.
862306a36Sopenharmony_ci
962306a36Sopenharmony_ciOverview
1062306a36Sopenharmony_ci========
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ciMHI is a protocol developed by Qualcomm Innovation Center, Inc. It is used
1362306a36Sopenharmony_ciby the host processors to control and communicate with modem devices over high
1462306a36Sopenharmony_cispeed peripheral buses or shared memory. Even though MHI can be easily adapted
1562306a36Sopenharmony_cito any peripheral buses, it is primarily used with PCIe based devices. MHI
1662306a36Sopenharmony_ciprovides logical channels over the physical buses and allows transporting the
1762306a36Sopenharmony_cimodem protocols, such as IP data packets, modem control messages, and
1862306a36Sopenharmony_cidiagnostics over at least one of those logical channels. Also, the MHI
1962306a36Sopenharmony_ciprotocol provides data acknowledgment feature and manages the power state of the
2062306a36Sopenharmony_cimodems via one or more logical channels.
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ciMHI Internals
2362306a36Sopenharmony_ci=============
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ciMMIO
2662306a36Sopenharmony_ci----
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ciMMIO (Memory mapped IO) consists of a set of registers in the device hardware,
2962306a36Sopenharmony_ciwhich are mapped to the host memory space by the peripheral buses like PCIe.
3062306a36Sopenharmony_ciFollowing are the major components of MMIO register space:
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ciMHI control registers: Access to MHI configurations registers
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ciMHI BHI registers: BHI (Boot Host Interface) registers are used by the host
3562306a36Sopenharmony_cifor downloading the firmware to the device before MHI initialization.
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ciChannel Doorbell array: Channel Doorbell (DB) registers used by the host to
3862306a36Sopenharmony_cinotify the device when there is new work to do.
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ciEvent Doorbell array: Associated with event context array, the Event Doorbell
4162306a36Sopenharmony_ci(DB) registers are used by the host to notify the device when new events are
4262306a36Sopenharmony_ciavailable.
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ciDebug registers: A set of registers and counters used by the device to expose
4562306a36Sopenharmony_cidebugging information like performance, functional, and stability to the host.
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ciData structures
4862306a36Sopenharmony_ci---------------
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ciAll data structures used by MHI are in the host system memory. Using the
5162306a36Sopenharmony_ciphysical interface, the device accesses those data structures. MHI data
5262306a36Sopenharmony_cistructures and data buffers in the host system memory regions are mapped for
5362306a36Sopenharmony_cithe device.
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_ciChannel context array: All channel configurations are organized in channel
5662306a36Sopenharmony_cicontext data array.
5762306a36Sopenharmony_ci
5862306a36Sopenharmony_ciTransfer rings: Used by the host to schedule work items for a channel. The
5962306a36Sopenharmony_citransfer rings are organized as a circular queue of Transfer Descriptors (TD).
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ciEvent context array: All event configurations are organized in the event context
6262306a36Sopenharmony_cidata array.
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ciEvent rings: Used by the device to send completion and state transition messages
6562306a36Sopenharmony_cito the host
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ciCommand context array: All command configurations are organized in command
6862306a36Sopenharmony_cicontext data array.
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ciCommand rings: Used by the host to send MHI commands to the device. The command
7162306a36Sopenharmony_cirings are organized as a circular queue of Command Descriptors (CD).
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ciChannels
7462306a36Sopenharmony_ci--------
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ciMHI channels are logical, unidirectional data pipes between a host and a device.
7762306a36Sopenharmony_ciThe concept of channels in MHI is similar to endpoints in USB. MHI supports up
7862306a36Sopenharmony_cito 256 channels. However, specific device implementations may support less than
7962306a36Sopenharmony_cithe maximum number of channels allowed.
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ciTwo unidirectional channels with their associated transfer rings form a
8262306a36Sopenharmony_cibidirectional data pipe, which can be used by the upper-layer protocols to
8362306a36Sopenharmony_citransport application data packets (such as IP packets, modem control messages,
8462306a36Sopenharmony_cidiagnostics messages, and so on). Each channel is associated with a single
8562306a36Sopenharmony_citransfer ring.
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ciTransfer rings
8862306a36Sopenharmony_ci--------------
8962306a36Sopenharmony_ci
9062306a36Sopenharmony_ciTransfers between the host and device are organized by channels and defined by
9162306a36Sopenharmony_ciTransfer Descriptors (TD). TDs are managed through transfer rings, which are
9262306a36Sopenharmony_cidefined for each channel between the device and host and reside in the host
9362306a36Sopenharmony_cimemory. TDs consist of one or more ring elements (or transfer blocks)::
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci        [Read Pointer (RP)] ----------->[Ring Element] } TD
9662306a36Sopenharmony_ci        [Write Pointer (WP)]-           [Ring Element]
9762306a36Sopenharmony_ci                             -          [Ring Element]
9862306a36Sopenharmony_ci                              --------->[Ring Element]
9962306a36Sopenharmony_ci                                        [Ring Element]
10062306a36Sopenharmony_ci
10162306a36Sopenharmony_ciBelow is the basic usage of transfer rings:
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci* Host allocates memory for transfer ring.
10462306a36Sopenharmony_ci* Host sets the base pointer, read pointer, and write pointer in corresponding
10562306a36Sopenharmony_ci  channel context.
10662306a36Sopenharmony_ci* Ring is considered empty when RP == WP.
10762306a36Sopenharmony_ci* Ring is considered full when WP + 1 == RP.
10862306a36Sopenharmony_ci* RP indicates the next element to be serviced by the device.
10962306a36Sopenharmony_ci* When the host has a new buffer to send, it updates the ring element with
11062306a36Sopenharmony_ci  buffer information, increments the WP to the next element and rings the
11162306a36Sopenharmony_ci  associated channel DB.
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ciEvent rings
11462306a36Sopenharmony_ci-----------
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ciEvents from the device to host are organized in event rings and defined by Event
11762306a36Sopenharmony_ciDescriptors (ED). Event rings are used by the device to report events such as
11862306a36Sopenharmony_cidata transfer completion status, command completion status, and state changes
11962306a36Sopenharmony_cito the host. Event rings are the array of EDs that resides in the host
12062306a36Sopenharmony_cimemory. EDs consist of one or more ring elements (or transfer blocks)::
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci        [Read Pointer (RP)] ----------->[Ring Element] } ED
12362306a36Sopenharmony_ci        [Write Pointer (WP)]-           [Ring Element]
12462306a36Sopenharmony_ci                             -          [Ring Element]
12562306a36Sopenharmony_ci                              --------->[Ring Element]
12662306a36Sopenharmony_ci                                        [Ring Element]
12762306a36Sopenharmony_ci
12862306a36Sopenharmony_ciBelow is the basic usage of event rings:
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci* Host allocates memory for event ring.
13162306a36Sopenharmony_ci* Host sets the base pointer, read pointer, and write pointer in corresponding
13262306a36Sopenharmony_ci  channel context.
13362306a36Sopenharmony_ci* Both host and device has a local copy of RP, WP.
13462306a36Sopenharmony_ci* Ring is considered empty (no events to service) when WP + 1 == RP.
13562306a36Sopenharmony_ci* Ring is considered full of events when RP == WP.
13662306a36Sopenharmony_ci* When there is a new event the device needs to send, the device updates ED
13762306a36Sopenharmony_ci  pointed by RP, increments the RP to the next element and triggers the
13862306a36Sopenharmony_ci  interrupt.
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ciRing Element
14162306a36Sopenharmony_ci------------
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ciA Ring Element is a data structure used to transfer a single block
14462306a36Sopenharmony_ciof data between the host and the device. Transfer ring element types contain a
14562306a36Sopenharmony_cisingle buffer pointer, the size of the buffer, and additional control
14662306a36Sopenharmony_ciinformation. Other ring element types may only contain control and status
14762306a36Sopenharmony_ciinformation. For single buffer operations, a ring descriptor is composed of a
14862306a36Sopenharmony_cisingle element. For large multi-buffer operations (such as scatter and gather),
14962306a36Sopenharmony_cielements can be chained to form a longer descriptor.
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_ciMHI Operations
15262306a36Sopenharmony_ci==============
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_ciMHI States
15562306a36Sopenharmony_ci----------
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ciMHI_STATE_RESET
15862306a36Sopenharmony_ci~~~~~~~~~~~~~~~
15962306a36Sopenharmony_ciMHI is in reset state after power-up or hardware reset. The host is not allowed
16062306a36Sopenharmony_cito access device MMIO register space.
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ciMHI_STATE_READY
16362306a36Sopenharmony_ci~~~~~~~~~~~~~~~
16462306a36Sopenharmony_ciMHI is ready for initialization. The host can start MHI initialization by
16562306a36Sopenharmony_ciprogramming MMIO registers.
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ciMHI_STATE_M0
16862306a36Sopenharmony_ci~~~~~~~~~~~~
16962306a36Sopenharmony_ciMHI is running and operational in the device. The host can start channels by
17062306a36Sopenharmony_ciissuing channel start command.
17162306a36Sopenharmony_ci
17262306a36Sopenharmony_ciMHI_STATE_M1
17362306a36Sopenharmony_ci~~~~~~~~~~~~
17462306a36Sopenharmony_ciMHI operation is suspended by the device. This state is entered when the
17562306a36Sopenharmony_cidevice detects inactivity at the physical interface within a preset time.
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_ciMHI_STATE_M2
17862306a36Sopenharmony_ci~~~~~~~~~~~~
17962306a36Sopenharmony_ciMHI is in low power state. MHI operation is suspended and the device may
18062306a36Sopenharmony_cienter lower power mode.
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_ciMHI_STATE_M3
18362306a36Sopenharmony_ci~~~~~~~~~~~~
18462306a36Sopenharmony_ciMHI operation stopped by the host. This state is entered when the host suspends
18562306a36Sopenharmony_ciMHI operation.
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ciMHI Initialization
18862306a36Sopenharmony_ci------------------
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_ciAfter system boots, the device is enumerated over the physical interface.
19162306a36Sopenharmony_ciIn the case of PCIe, the device is enumerated and assigned BAR-0 for
19262306a36Sopenharmony_cithe device's MMIO register space. To initialize the MHI in a device,
19362306a36Sopenharmony_cithe host performs the following operations:
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_ci* Allocates the MHI context for event, channel and command arrays.
19662306a36Sopenharmony_ci* Initializes the context array, and prepares interrupts.
19762306a36Sopenharmony_ci* Waits until the device enters READY state.
19862306a36Sopenharmony_ci* Programs MHI MMIO registers and sets device into MHI_M0 state.
19962306a36Sopenharmony_ci* Waits for the device to enter M0 state.
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_ciMHI Data Transfer
20262306a36Sopenharmony_ci-----------------
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_ciMHI data transfer is initiated by the host to transfer data to the device.
20562306a36Sopenharmony_ciFollowing are the sequence of operations performed by the host to transfer
20662306a36Sopenharmony_cidata to device:
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_ci* Host prepares TD with buffer information.
20962306a36Sopenharmony_ci* Host increments the WP of the corresponding channel transfer ring.
21062306a36Sopenharmony_ci* Host rings the channel DB register.
21162306a36Sopenharmony_ci* Device wakes up to process the TD.
21262306a36Sopenharmony_ci* Device generates a completion event for the processed TD by updating ED.
21362306a36Sopenharmony_ci* Device increments the RP of the corresponding event ring.
21462306a36Sopenharmony_ci* Device triggers IRQ to wake up the host.
21562306a36Sopenharmony_ci* Host wakes up and checks the event ring for completion event.
21662306a36Sopenharmony_ci* Host updates the WP of the corresponding event ring to indicate that the
21762306a36Sopenharmony_ci  data transfer has been completed successfully.
21862306a36Sopenharmony_ci
219