HSI

=What is HSI ?= The MIPI High Speed Synchronous Serial Interface (HSI) is a high speed communication interface that is used for connecting OMAP to a cellular modem engine. It is specified by the MIPI alliance (www.mipi.org). An introduction to the MIPI HSI working group can be found here: http://www.mipi.org/working-groups/high-speed-synchronous-interface

The HSI interface supports full duplex communication over multiple channels and is capable of reaching speeds up to 200 Mbit/s.

HSI link is the recommended IPC for OMAP4 modem connectivity. It offers a high speed multi-channel interface to connect 3G and 4G (up to LTE Category 3) modems. The OMAP HSI driver supports both OMAP MIPI HSI (as defined in MIPI documentation mipi_HSI-PL_specification_v01-01-00a.pdf) and OMAP SSI devices through different device files, and a generic SW driver.



Please refer to the MIPI specifications for more details on this device: http://www.mipi.org/specifications/high-speed-synchronous-serial-interface-hsi

=A little background on HSI driver=

There are 2 HSI drivers : One owned by Modem Integration team (Google Hub), one owned by LDC(TI Linux Development Center).

HSI Driver 1: Modem Integration HSI driver
 * this is HSI driver currently present in p-android-omap-2.6.35, p-android-omap-3.0 and p-android-omap-3.1 (kernel/drivers/omap_hsi) and currently in production since K2.6.35
 * This driver is the one used by all customers using STE, IMC or Renesas modems (Samsung, LGE, Moto, Huawei, PMC etc…) on OMAP4.
 * This driver will also be used on OMAP5 by STE POR modem
 * Additionally this driver also support various Link Layers on top of it (every modem partner or customer has its own Link Layer).
 * This driver is pretty mature and changes are :
 * bug fixes are mainly to fix the issues seen at customers to comply with changes in modem side or Link Layer.
 * Kernel framework changes (PM, mux, hwmod, etc…)
 * All patches are pushed to Gerrit
 * Owner is Elaidi, Djamil (Modem Integration team, Google Hub)

Driver 2: LDC HSI driver, based on Nokia RFC
 * This is a whole new driver, with 0% lines in common with previous HSI driver.
 * Purpose of this LDC new driver is to upstream
 * Nokia started this upstream driver in 2010 for SSI, and it is still not upstream, since a lot of people in open source community are also contributing.
 * LDC started in 2Q2011 to develop a OMAP HSI version of this driver
 * Timeframe for driver upstream is unknown.
 * From the beginning Modem Integration team and LDC agreed that this driver will not be ready in time for OMAP5
 * Fixes posted in Gerrit for Modem Integration HSI driver shall be watched and absorbed by LDC team owning the LDC HSI driver.
 * Since the 2 drivers are completely differents, patches for Modem Integration HSI driver cannot apply directly to LDC HSI driver
 * Owner is Datta, Shubhrajyoti (LDC)

So as there are 2 HSI drivers, one shall not confuse the 2 of them. Patches pushed in Gerrit and merged to TI android branches only concern Modem Integration HSI driver (Driver 1).

The current page refers only to android HSI driver (Driver 1)

=Where is HSI driver ?=

In TI Android mainlines
HSI driver is part of TI official releases for Android OMAP4 and OMAP5. TI branches containing HSI driver are at http://review.omapzoom.org :
 * On Kernel 2.6.35, Source code is available in branch p-android-omap-2.6.35 under directory [kernel/omap.git]/drivers/staging/omap_hsi/


 * On Kernel 3.0, Source code is available in branch p-android-omap-3.0 under directory [kernel/omap.git]/drivers/omap_hsi/


 * On Kernel 3.1, Source code is available in branch p-android-omap-3.1 under directory [kernel/omap.git]/drivers/omap_hsi/


 * On Kernel 3.4, Source code is available in branch p-android-omap-3.4 under directory [kernel/omap.git]/drivers/omap_hsi/

Ex.for K3.1: http://git.omapzoom.org/?p=kernel/omap.git;a=tree;f=drivers/omap_hsi;h=ae899ab1abae144eeb6d61da64b5b68c58b19766;hb=refs/heads/p-android-omap-3.1

In HSI feature tree
HSI driver feature tree for K3.0 and higher is https://gitorious.tif.ti.com/modem-integration/mipi-hsi

=Linux HSI Physical Driver=

The HSI kernel documentation is available here:
 * Kernel 2.6.35:


 * Kernel 3.1:

Services provided by the Linux HSI driver

 * The Linux HSI driver implements the PHYsical layer.
 * Management of:
 * WAKE, DATA, FLAG and READY signals following SSI/HSI specifications
 * RX/TX state machines
 * HSI FIFOs
 * HSI DMA
 * Transmission mode (stream/frame)
 * Errors
 * HSI power Management: HSI_Power_Management
 * platform wake-up related to modem events (through HSI wake line)
 * Generic abstraction layer: provides an HSI virtual BUS and HSI virtual devices for each channel, mapped on HSI logical channels
 * Kernel space interface and optional user space interface


 * Services NOT provided (belong to higher SW layers):
 * Management of platform reset
 * Data Link Protocol / assignment of channels to dedicated roles (control / data)
 * Synchronize / inform peer of transactions on the link and transmission parameters (speed, mode, flow, number of channels, …)
 * Synchronize PM states between modem and ABE (Frequency and voltage changes)

HSI Linux driver kernel interfaces

 * Register an HSI driver, to use a pre-defined set of HSI ports / channels
 * open / read / write / configuration operations on HSI channels
 * Callbacks for read / write complete and asynchronous events (errors, break frames)

HSI Power Management
HSI power management requires a shared alignment between the modem partner & TI.


 * HSI Data Link Protocol driver responsibility. The Wake lines Management requires upper-layer SW control, dependent on the modem protocol:
 * ACWAKE is explicitly asserted and reset under HSI DLP driver control
 * CAWAKE change events are reported to HSI DLP driver


 * OMAP HSI physical driver responsability
 * OMAP4 HSI IP Clock management (functional and interface clocks)
 * OFF mode Wake-up
 * Requires OMAP IO daisy chain SW mechanism
 * Requires Context Save/Restore SW mechanism
 * The HSI HW context is saved automatically by the SW driver when entering OFF mode and restored upon wake-up.
 * OPP change
 * To sustain 21 mbps throughput, HSI link speed at 48/52MHz is sufficient. Functional clock is setup at 96 Mhz.

OMAP4 MIPI HSI Power management rules
Note : « wake-up » or « sleep » are related to HSI HW state, not OMAP or Modem state.
 * WAKE lines protocol rules :
 * Wake-up
 * Both OMAP and Modem can initiate a wakeup by raising their WAKE line
 * Low power mode
 * OMAP HSI can enter into LPM only once ACWAKE and CAWAKE lines are low.

=HSI debug=

HSI dynamic debug
HSI driver uses dynamic debug feature of kernel. Here is what to do to enable it :

Build kernel with : CONFIG_DYNAMIC_DEBUG=y

After boot :
 * mount -t debugfs debugfs 

Usually is /d or /debugfs


 * echo -n 'module omap_hsi +p' > / /dynamic_debug/control

but this is a lot of trace, so you can remove the one that you consider as spam for this issue by :


 * cat / /dynamic_debug/control | grep hsi
 * echo -n 'file hsi_driver_bus.c line 201 -p' > / /dynamic_debug/control
 * etc...


 * To add a single trace
 * echo -n 'file hsi_driver_bus.c line 201 +p' > / /dynamic_debug/control


 * To remove a single trace
 * echo -n 'file hsi_driver_bus.c line 201 -p' > / /dynamic_debug/control


 * To add all traces for complete hsi module
 * echo -n 'module omap_hsi +p' > / /dynamic_debug/control
 * echo -n 'module hsi_char +p' > / /dynamic_debug/control


 * To remove all traces for complete hsi module
 * echo -n 'module omap_hsi -p' > / /dynamic_debug/control
 * echo -n 'module hsi_char -p' > / /dynamic_debug/control

As a first step, I recommend setting the following traces only :
 * Minimum traces


 * Wakeup
 * ''echo -n 'func omap_hsi_wakeup +p' > / /dynamic_debug/control
 * echo -n 'func hsi_do_cawake_process +p' > / /dynamic_debug/control
 * echo -n 'func omap_hsi_wakeup_enable +p' > / /dynamic_debug/control
 * echo -n 'func omap_hsi_wakeup_disable +p' > / /dynamic_debug/control''


 * Clocks
 * ''echo -n 'func hsi_clocks_enable_channel +p' > / /dynamic_debug/control
 * echo -n 'func hsi_clocks_disable_channel +p' > / /dynamic_debug/control
 * echo -n 'func hsi_runtime_resume +p' > / /dynamic_debug/control
 * echo -n 'func hsi_runtime_suspend +p' > / /dynamic_debug/control
 * echo -n 'func hsi_runtime_idle +p' > / /dynamic_debug/control
 * echo -n 'func hsi_pm_prepare +p' > / /dynamic_debug/control
 * echo -n 'func hsi_pm_suspend +p' > / /dynamic_debug/control
 * echo -n 'func hsi_pm_suspend_noirq +p' > / /dynamic_debug/control
 * echo -n 'func hsi_pm_resume +p' > / /dynamic_debug/control''


 * R/W
 * ''echo -n 'func hsi_write +p' > / /dynamic_debug/control
 * echo -n 'func hsi_read +p' > / /dynamic_debug/control
 * echo -n 'func do_hsi_gdd_lch +p' > / /dynamic_debug/control
 * echo -n 'func hsi_do_channel_rx +p' > / /dynamic_debug/control
 * echo -n 'func hsi_do_channel_tx +p' > / /dynamic_debug/control''

You should obtain something like: example: <7>omap_hsi omap_hsi.0: Int Tasklet : clock_enabled=1 <7>omap_hsi omap_hsi.0: CLK: hsi_clocks_enable: do_hsi_tasklet <7>omap_hsi omap_hsi.0: Clocks already enabled, skipping... <7>omap_hsi omap_hsi.0: Channels [0,7] : Events 0x00000100 <7>omap_hsi omap_hsi.0: Data Available interrupt for channel 0. <7>omap_hsi omap_hsi.0: Channels [8,15] : no event, exit. <7>omap_hsi omap_hsi.0: CLK: hsi_clocks_disable: do_hsi_tasklet <7>omap_hsi omap_hsi.0: Port 1: WAKE status: acwake_status 1,cur_cawake 1 <7>omap_hsi omap_hsi.0: Port 1 busy <7>omap_hsi omap_hsi.0: Cannot disable clocks, HSI port busy <7>omap_hsi omap_hsi.0: Int Tasklet : clock_enabled=1 <7>omap_hsi omap_hsi.0: CLK: hsi_clocks_enable: do_hsi_tasklet
 * Trace output example

HSI core debug
HSI Driver has a debugfs directory, where you can access all the HSI registers: / /hsi/omap_hsi0/

E.g. cat / /hsi/omap_hsi0/port1/regs cat / /hsi/omap_hsi0/port1/counters cat / /hsi/omap_hsi0/regs cat / /hsi/omap_hsi0/gdd/regs

HSI Power Management debug
TBC

=HSI Standalone Testing=

Test code location
Where to get the hsi_test and hsi_perf code ? git clone git@gitorious.tif.ti.com:modem-integration/hsi-test.git

Public url will come soon.

Test setup
Running these tests imply having setup the following: 1) a test platform (board) hosting a compatible HSI device 2) Either: plug 2 boards together through their HSI port 1 (1st HSI port): HSI Tx wires of board 1 connected to HSI Rx wires of board 2 HSI Rx wires of board 1 connected to HSI Tx wires of board 2 or loopback the HSI signals of HSI port 1 of a single test board: ACwake <-> CAWake ACReady <-> CAReady ACData <-> CAData ACFlag <-> CAFlag or connect the OMAP HSI to a modem and perform loopback in the modem

hsi_test
This test application is used to debug and test the HSI device drivers by interfacing at HSI char driver level. It is a user space application that has no dependency on the kernel, except for the IOCTL constants definitions appearing in hsi_char.h (although these constants could be re-defined locally).

The test application can use up to 4 HSI channels simultaneously, but for most of tests, only channel 0 is used. Note that when only channel 0 is required, the other channels are not opened. The HSI port 1 (1st HSI port) is used. Port 2 is not used with this setting.

hsi_perf
The HSI throughput measurement module is an out-of-tree kernel module, used to measure the HSI driver throughput in various configurations. This module sends and receives data using loopback mode. It doesn't check the validity of the received data vs what was sent previously. The test starts immediatly when hsi_perf module is loaded.

hsi_perf architecture information
This section is dedicated to help anyone who would like to look into the hsi_perf module code.

When loaded, hsi_perf module will :
 * register itself as a user of HSI driver
 * open the required number of channels and configure the TX and RX parameters
 * create as many kernel threads for write as there are channels opened
 * create as many kernel threads for read as there are channels opened
 * create one kernel thread to display measurement results

Synchronisation between kernel threads : hsi_perf uses mutexes and R/W semaphores to synchronize between kernel threads and make sure every thread starts when needed.

For each channel, 2 mutexes are created :
 * one to start a new write once previous write is over
 * one to start a new read once previous read is over

Also, there is a Read/Write semaphore used to allow the display measurement kthread to be run once all other read and write are over : until all reader smeaphores are released
 * Every read or write kernel thread created will acquire a reader semaphore
 * Every complete read or write will release a reader semaphore
 * The display measurement kthread will try to acquire a writer semaphore, which will cause the kthread to sleep

HSI Test points on OMAP44xx Processor board
=HSI warning & error message interpretation=
 * Missed previous CAWAKE falling edge
 * This trace occurs


 * Missed previous CAWAKE rising edge
 * This trace is printed if the following sequence occurs :
 * CAWAKE is low and HSI is inactive, eg. :
 * HSI clocks have been disabled
 * HSI wakeup event now goes through IO Daisy chain mechanism
 * HSI internal variable cawake_status is set to 0
 * Modem wants to transmit to OMAP, so CAWAKE goes high, so OMAP is awaken,
 * PRCM interrupt is raised and HSI tasklet is scheduled
 * Before HSI tasklet has been completed to process CAWAKE rising edge and cawake_status can be set to 1, CAWAKE goes low again
 * So HSI tasklet is fooled by the new value of CAWAKE (low) and thinks it is a falling edge. But when HSI compares to previous cawake_status value, it founds out that CAWAKE was already low. So HSI driver knows there has been a missed CAWAKE rising edge and prints the warning message “Missed previous CAWAKE rising edge”


 * I have measured that if CAWAKE goes low less than 1.2ms after CAWAKE went high, then this error is triggered. So time between point 1 and 4 shall be more than 1.2ms. of course this depends on CPU load, etc…


 * New CAWAKE interrupt detected during interrupt processing
 * This trace occurs