High Speed Synchronous Serial Interface (HSI)

Introduction

High Speed Synchronous Interface (HSI) is a full duplex, low latency protocol,that is optimized for die-level interconnect between an Application Processorand a Baseband chipset. It has been specified by the MIPI alliance in 2003 andimplemented by multiple vendors since then.

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

The serial protocol uses two signals, DATA and FLAG as combined data and clocksignals and an additional READY signal for flow control. An additional WAKEsignal can be used to wakeup the chips from standby modes. The signals arecommonly prefixed by AC for signals going from the application die to thecellular die and CA for signals going the other way around.

+------------+                                 +---------------+|  Cellular  |                                 |  Application  ||    Die     |                                 |      Die      ||            | - - - - - - CAWAKE - - - - - - >|               ||           T|------------ CADATA ------------>|R              ||           X|------------ CAFLAG ------------>|X              ||            |<----------- ACREADY ------------|               ||            |                                 |               ||            |                                 |               ||            |< - - - - -  ACWAKE - - - - - - -|               ||           R|<----------- ACDATA -------------|T              ||           X|<----------- ACFLAG -------------|X              ||            |------------ CAREADY ----------->|               ||            |                                 |               ||            |                                 |               |+------------+                                 +---------------+

HSI Subsystem in Linux

In the Linux kernel the hsi subsystem is supposed to be used for HSI devices.The hsi subsystem contains drivers for hsi controllers including support formulti-port controllers and provides a generic API for using the HSI ports.

It also contains HSI client drivers, which make use of the generic API toimplement a protocol used on the HSI interface. These client drivers canuse an arbitrary number of channels.

hsi-char Device

Each port automatically registers a generic client driver called hsi_char,which provides a character device for userspace representing the HSI port.It can be used to communicate via HSI from userspace. Userspace mayconfigure the hsi_char device using the following ioctl commands:

HSC_RESET

flush the HSI port

HSC_SET_PM

enable or disable the client.

HSC_SEND_BREAK

send break

HSC_SET_RX

set RX configuration

HSC_GET_RX

get RX configuration

HSC_SET_TX

set TX configuration

HSC_GET_TX

get TX configuration

The kernel HSI API

structhsi_channel

channel resource used by the hsi clients

Definition:

struct hsi_channel {    unsigned int    id;    const char      *name;};

Members

id

Channel number

name

Channel name

structhsi_config

Configuration for RX/TX HSI modules

Definition:

struct hsi_config {    unsigned int            mode;    struct hsi_channel      *channels;    unsigned int            num_channels;    unsigned int            num_hw_channels;    unsigned int            speed;    union {        unsigned int    flow;        unsigned int    arb_mode;    };};

Members

mode

Bit transmission mode (STREAM or FRAME)

channels

Channel resources used by the client

num_channels

Number of channel resources

num_hw_channels

Number of channels the transceiver is configured for [1..16]

speed

Max bit transmission speed (Kbit/s)

{unnamed_union}

anonymous

flow

RX flow type (SYNCHRONIZED or PIPELINE)

arb_mode

Arbitration mode for TX frame (Round robin, priority)

structhsi_board_info

HSI client board info

Definition:

struct hsi_board_info {    const char              *name;    unsigned int            hsi_id;    unsigned int            port;    struct hsi_config       tx_cfg;    struct hsi_config       rx_cfg;    void *platform_data;    struct dev_archdata     *archdata;};

Members

name

Name for the HSI device

hsi_id

HSI controller id where the client sits

port

Port number in the controller where the client sits

tx_cfg

HSI TX configuration

rx_cfg

HSI RX configuration

platform_data

Platform related data

archdata

Architecture-dependent device data

structhsi_client

HSI client attached to an HSI port

Definition:

struct hsi_client {    struct device           device;    struct hsi_config       tx_cfg;    struct hsi_config       rx_cfg;};

Members

device

Driver model representation of the device

tx_cfg

HSI TX configuration

rx_cfg

HSI RX configuration

structhsi_client_driver

Driver associated to an HSI client

Definition:

struct hsi_client_driver {    struct device_driver    driver;};

Members

driver

Driver model representation of the driver

structhsi_msg

HSI message descriptor

Definition:

struct hsi_msg {    struct list_head        link;    struct hsi_client       *cl;    struct sg_table         sgt;    void *context;    void (*complete)(struct hsi_msg *msg);    void (*destructor)(struct hsi_msg *msg);    int status;    unsigned int            actual_len;    unsigned int            channel;    unsigned int            ttype:1;    unsigned int            break_frame:1;};

Members

link

Free to use by the current descriptor owner

cl

HSI device client that issues the transfer

sgt

Head of the scatterlist array

context

Client context data associated to the transfer

complete

Transfer completion callback

destructor

Destructor to free resources when flushing

status

Status of the transfer when completed

actual_len

Actual length of data transferred on completion

channel

Channel were to TX/RX the message

ttype

Transfer type (TX if set, RX otherwise)

break_frame

if true HSI will send/receive a break frame. Data buffers areignored in the request.

structhsi_port

HSI port device

Definition:

struct hsi_port {    struct device                   device;    struct hsi_config               tx_cfg;    struct hsi_config               rx_cfg;    unsigned int                    num;    unsigned int                    shared:1;    int claimed;    struct mutex                    lock;    int (*async)(struct hsi_msg *msg);    int (*setup)(struct hsi_client *cl);    int (*flush)(struct hsi_client *cl);    int (*start_tx)(struct hsi_client *cl);    int (*stop_tx)(struct hsi_client *cl);    int (*release)(struct hsi_client *cl);    struct blocking_notifier_head   n_head;};

Members

device

Driver model representation of the device

tx_cfg

Current TX path configuration

rx_cfg

Current RX path configuration

num

Port number

shared

Set when port can be shared by different clients

claimed

Reference count of clients which claimed the port

lock

Serialize port claim

async

Asynchronous transfer callback

setup

Callback to set the HSI client configuration

flush

Callback to clean the HW state and destroy all pending transfers

start_tx

Callback to inform that a client wants to TX data

stop_tx

Callback to inform that a client no longer wishes to TX data

release

Callback to inform that a client no longer uses the port

n_head

Notifier chain for signaling port events to the clients.

structhsi_controller

HSI controller device

Definition:

struct hsi_controller {    struct device           device;    struct module           *owner;    unsigned int            id;    unsigned int            num_ports;    struct hsi_port         **port;};

Members

device

Driver model representation of the device

owner

Pointer to the module owning the controller

id

HSI controller ID

num_ports

Number of ports in the HSI controller

port

Array of HSI ports

unsignedinthsi_id(structhsi_client*cl)

Get HSI controller ID associated to a client

Parameters

structhsi_client*cl

Pointer to a HSI client

Description

Return the controller id where the client is attached to

unsignedinthsi_port_id(structhsi_client*cl)

Gets the port number a client is attached to

Parameters

structhsi_client*cl

Pointer to HSI client

Description

Return the port number associated to the client

inthsi_setup(structhsi_client*cl)

Configure the client’s port

Parameters

structhsi_client*cl

Pointer to the HSI client

Description

When sharing ports, clients should either relay on a singleclient setup or have the same setup for all of them.

Return -errno on failure, 0 on success

inthsi_flush(structhsi_client*cl)

Flush all pending transactions on the client’s port

Parameters

structhsi_client*cl

Pointer to the HSI client

Description

This function will destroy all pending hsi_msg in the port and resetthe HW port so it is ready to receive and transmit from a clean state.

Return -errno on failure, 0 on success

inthsi_async_read(structhsi_client*cl,structhsi_msg*msg)

Submit a read transfer

Parameters

structhsi_client*cl

Pointer to the HSI client

structhsi_msg*msg

HSI message descriptor of the transfer

Description

Return -errno on failure, 0 on success

inthsi_async_write(structhsi_client*cl,structhsi_msg*msg)

Submit a write transfer

Parameters

structhsi_client*cl

Pointer to the HSI client

structhsi_msg*msg

HSI message descriptor of the transfer

Description

Return -errno on failure, 0 on success

inthsi_start_tx(structhsi_client*cl)

Signal the port that the client wants to start a TX

Parameters

structhsi_client*cl

Pointer to the HSI client

Description

Return -errno on failure, 0 on success

inthsi_stop_tx(structhsi_client*cl)

Signal the port that the client no longer wants to transmit

Parameters

structhsi_client*cl

Pointer to the HSI client

Description

Return -errno on failure, 0 on success

voidhsi_port_unregister_clients(structhsi_port*port)

Unregister an HSI port

Parameters

structhsi_port*port

The HSI port to unregister

voidhsi_unregister_controller(structhsi_controller*hsi)

Unregister an HSI controller

Parameters

structhsi_controller*hsi

The HSI controller to register

inthsi_register_controller(structhsi_controller*hsi)

Register an HSI controller and its ports

Parameters

structhsi_controller*hsi

The HSI controller to register

Description

Returns -errno on failure, 0 on success.

inthsi_register_client_driver(structhsi_client_driver*drv)

Register an HSI client to the HSI bus

Parameters

structhsi_client_driver*drv

HSI client driver to register

Description

Returns -errno on failure, 0 on success.

voidhsi_put_controller(structhsi_controller*hsi)

Free an HSI controller

Parameters

structhsi_controller*hsi

Pointer to the HSI controller to freed

Description

HSI controller drivers should only use this function if they needto free their allocated hsi_controller structures before a successfulcall to hsi_register_controller. Other use is not allowed.

structhsi_controller*hsi_alloc_controller(unsignedintn_ports,gfp_tflags)

Allocate an HSI controller and its ports

Parameters

unsignedintn_ports

Number of ports on the HSI controller

gfp_tflags

Kernel allocation flags

Description

Return NULL on failure or a pointer to an hsi_controller on success.

voidhsi_free_msg(structhsi_msg*msg)

Free an HSI message

Parameters

structhsi_msg*msg

Pointer to the HSI message

Description

Client is responsible to free the buffers pointed by the scatterlists.

structhsi_msg*hsi_alloc_msg(unsignedintnents,gfp_tflags)

Allocate an HSI message

Parameters

unsignedintnents

Number of memory entries

gfp_tflags

Kernel allocation flags

Description

nents can be 0. This mainly makes sense for read transfer.In that case, HSI drivers will call the complete callback whenthere is data to be read without consuming it.

Return NULL on failure or a pointer to an hsi_msg on success.

inthsi_async(structhsi_client*cl,structhsi_msg*msg)

Submit an HSI transfer to the controller

Parameters

structhsi_client*cl

HSI client sending the transfer

structhsi_msg*msg

The HSI transfer passed to controller

Description

The HSI message must have the channel, ttype, complete and destructorfields set beforehand. If nents > 0 then the client has to initializealso the scatterlists to point to the buffers to write to or read from.

HSI controllers relay on pre-allocated buffers from their clients and theydo not allocate buffers on their own.

Once the HSI message transfer finishes, the HSI controller calls thecomplete callback with the status and actual_len fields of the HSI messageupdated. The complete callback can be called before returning fromhsi_async.

Returns -errno on failure or 0 on success

inthsi_claim_port(structhsi_client*cl,unsignedintshare)

Claim the HSI client’s port

Parameters

structhsi_client*cl

HSI client that wants to claim its port

unsignedintshare

Flag to indicate if the client wants to share the port or not.

Description

Returns -errno on failure, 0 on success.

voidhsi_release_port(structhsi_client*cl)

Release the HSI client’s port

Parameters

structhsi_client*cl

HSI client which previously claimed its port

inthsi_register_port_event(structhsi_client*cl,void(*handler)(structhsi_client*,unsignedlong))

Register a client to receive port events

Parameters

structhsi_client*cl

HSI client that wants to receive port events

void(*handler)(structhsi_client*,unsignedlong)

Event handler callback

Description

Clients should register a callback to be able to receiveevents from the ports. Registration should happen afterclaiming the port.The handler can be called in interrupt context.

Returns -errno on error, or 0 on success.

inthsi_unregister_port_event(structhsi_client*cl)

Stop receiving port events for a client

Parameters

structhsi_client*cl

HSI client that wants to stop receiving port events

Description

Clients should call this function before releasing their associatedport.

Returns -errno on error, or 0 on success.

inthsi_event(structhsi_port*port,unsignedlongevent)

Notifies clients about port events

Parameters

structhsi_port*port

Port where the event occurred

unsignedlongevent

The event type

Description

Clients should not be concerned about wake line behavior. However, dueto a race condition in HSI HW protocol, clients need to be notifiedabout wake line changes, so they can implement a workaround for it.

Events:HSI_EVENT_START_RX - Incoming wake line highHSI_EVENT_STOP_RX - Incoming wake line down

Returns -errno on error, or 0 on success.

inthsi_get_channel_id_by_name(structhsi_client*cl,char*name)

acquire channel id by channel name

Parameters

structhsi_client*cl

HSI client, which uses the channel

char*name

name the channel is known under

Description

Clients can call this function to get the hsi channel ids similar torequesting IRQs or GPIOs by name. This function assumes the samechannel configuration is used for RX and TX.

Returns -errno on error or channel id on success.