HSI

From OMAPpedia

Revision as of 13:21, 9 October 2012 by Cpoignet (Talk | contribs)
Jump to: navigation, search

Contents

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.

MIPI HSI.jpg

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 drivers

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


Driver 2: LDC HSI driver, based on Nokia RFC

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 OMAP HSI Physical Driver (omap_hsi)

The OMAP HSI driver kernel documentation is available here:

Kernel 2.6.35: [1]
Kernel 3.1: [2]

Services provided by the Linux HSI driver

HSI Linux driver kernel interfaces

HSI Throughput measurements

Basic rules to reach maximum throughput

Additional rules to reach maximum throughput


Full details can be found here: File:HSI thoughput perf v0.7.pdf

HSI Power Management

Responsibilities Split

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

System must be kept awake as long as a RX/TX is ongoing (usage of wakelock by upper layers )

OMAP4 MIPI HSI Power management rules

Note : « wake-up » or « sleep » are related to HSI HW state, not OMAP or Modem state.

HSI Dynamic OPP change

Full details can be found here: File:HSI PM dyn opp change v0.6.pdf

Background

Implementation

Interface with upper layers

Latencies

Wakeup and sleep

Runtime suspend and resume

Since kernel 2.6.35, HSI driver fully supports runtime PM. HSI driver enables and disables HSI Functional clock (FClk) and HSI Interface Clock(IClk) on a need basis. This is done using runtime PM APIs pm_runtime_get_sync() and pm_runtime_put_sync_suspend().

Every time an HSI access is needed, HSI driver enables the clocks. Once HSI HW access is over, HSI driver disables the clocks if the HSI controller is not busy.

HSI controller is declared busy if one of the following conditions is true: For all port of the HSI controller:

Platform suspend and resume

When entering system wide suspend, the following hooks are called :

These hooks correspond to the differents phases of entering system suspend (cf. <kernel>\Documentation\power\devices.txt) Each of these hooks gives a chance to HSI driver to prevent the system suspend. Any of these hooks will return -EBUSY if HSI is busy (cf. conditions here)


Pros of this implementation:

Cons of this implementation:

Port 2 support

HSI supports Port 2 usage from kernel 3.1 and higher.

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 <debugfs>

Usually <debugfs> is /d or /debugfs

echo -n 'module omap_hsi +p' > /<debugfs>/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 /<debugfs>/dynamic_debug/control | grep hsi
echo -n 'file hsi_driver_bus.c line 201 -p' > /<debugfs>/dynamic_debug/control
etc...
To add a single trace
echo -n 'file hsi_driver_bus.c line 201 +p' > /<debugfs>/dynamic_debug/control
To remove a single trace
echo -n 'file hsi_driver_bus.c line 201 -p' > /<debugfs>/dynamic_debug/control
To add all traces for complete hsi module
echo -n 'module omap_hsi +p' > /<debugfs>/dynamic_debug/control
echo -n 'module hsi_char +p' > /<debugfs>/dynamic_debug/control
To remove all traces for complete hsi module
echo -n 'module omap_hsi -p' > /<debugfs>/dynamic_debug/control
echo -n 'module hsi_char -p' > /<debugfs>/dynamic_debug/control
Minimum traces

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

echo -n 'func omap_hsi_wakeup +p' > /<debugfs>/dynamic_debug/control
echo -n 'func hsi_do_cawake_process +p' > /<debugfs>/dynamic_debug/control
echo -n 'func omap_hsi_wakeup_enable +p' > /<debugfs>/dynamic_debug/control
echo -n 'func omap_hsi_wakeup_disable +p' > /<debugfs>/dynamic_debug/control
echo -n 'func hsi_clocks_enable_channel +p' > /<debugfs>/dynamic_debug/control
echo -n 'func hsi_clocks_disable_channel +p' > /<debugfs>/dynamic_debug/control
echo -n 'func hsi_runtime_resume +p' > /<debugfs>/dynamic_debug/control
echo -n 'func hsi_runtime_suspend +p' > /<debugfs>/dynamic_debug/control
echo -n 'func hsi_runtime_idle +p' > /<debugfs>/dynamic_debug/control
echo -n 'func hsi_pm_prepare +p' > /<debugfs>/dynamic_debug/control
echo -n 'func hsi_pm_suspend +p' > /<debugfs>/dynamic_debug/control
echo -n 'func hsi_pm_suspend_noirq +p' > /<debugfs>/dynamic_debug/control
echo -n 'func hsi_pm_resume +p' > /<debugfs>/dynamic_debug/control
echo -n 'func hsi_write +p' > /<debugfs>/dynamic_debug/control
echo -n 'func hsi_read +p' > /<debugfs>/dynamic_debug/control
echo -n 'func do_hsi_gdd_lch +p' > /<debugfs>/dynamic_debug/control
echo -n 'func hsi_do_channel_rx +p' > /<debugfs>/dynamic_debug/control
echo -n 'func hsi_do_channel_tx +p' > /<debugfs>/dynamic_debug/control
Trace output example

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

HSI core debug

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

E.g. cat /<debugfs>/hsi/omap_hsi0/port1/regs cat /<debugfs>/hsi/omap_hsi0/port1/counters cat /<debugfs>/hsi/omap_hsi0/regs cat /<debugfs>/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 :

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 :

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

HSI Test points on OMAP44xx Processor board

Signal name OMAP4430/ OMAP4460 OMAP5430
h_HSI_CADATATP35
h_HSI_CAFLAGTP36
h_HSI_ACREADYTP44
h_HSI_ACDATATP37
h_HSI_ACWAKETP45
h_HSI_CAWAKETP38
h_HSI_CAREADYTP46
h_HSI_ACFLAGTP39

HSI warning & error message interpretation

Missed previous CAWAKE falling edge

This trace means a CAWAKE low glitch has been detected by HSI driver e.g.CAWAKE has toggled to low (High->Low->High transition) for a very short time, insufficient for the HSI tasklet to process correctly the CAWAKE low event.
This trace is printed if the following sequence occurs :
  1. CAWAKE is high and HSI is active, eg. :
    • HSI clocks are enabled
    • HSI wakeup event doesn't use IO Daisy chain mechanism
    • HSI internal variable cawake_status is set to 1
  2. CAWAKE goes low for a vey short period (less than 600us)
  3. HSI tasklet is scheduled to process the CAWAKE low event
  4. Before HSI tasklet has been executed to process CAWAKE falling edge and cawake_status can be set to 0, CAWAKE goes high again
  5. So HSI tasklet is fooled by the new value of CAWAKE (high) and thinks it is a rising edge. But when HSI compares to previous cawake_status value, it founds out that CAWAKE was already high. So HSI driver knows there has been a missed CAWAKE falling edge and prints the warning message “Missed previous CAWAKE falling edge”

HSI driver is able to recover from such a warning.

Missed previous CAWAKE rising edge

This trace is printed if the following sequence occurs :
  1. 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
  2. Modem wants to transmit to OMAP, so CAWAKE goes high, so OMAP is awaken,
  3. PRCM interrupt is raised and HSI tasklet is scheduled
  4. Before HSI tasklet has been completed to process CAWAKE rising edge and cawake_status can be set to 1, CAWAKE goes low again
  5. 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…

HSI driver is able to recover from such a warning.

New CAWAKE interrupt detected during interrupt processing

This trace occurs when HSI tasklet is executing and processing a CAWAKE event (high or low) and another CAWAKE event occurs while previous processign is not yet over.

HSI driver is able to recover from such a warning.

Personal tools
Namespaces
Variants
Actions
Navigation
Toolbox