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