OMAP SSI API's How To
=====================

The Synchronous Serial Interface (SSI) is a high speed communication interface
that is used for connecting OMAP to a cellular modem engine.

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

I OMAP SSI driver API overview
-----------------------------

A) SSI Bus, SSI channels and protocol drivers overview.

The OMAP SSI driver is intended to be used inside the kernel by protocol drivers.

The OMAP SSI abstracts the concept of SSI channels by creating an SSI bus an
attaching SSI channel devices to it.(see Figure 1)

Protocol drivers will then claim one or more SSI channels, after registering with the OMAP SSI driver.

	+---------------------+		+----------------+
	+  SSI channel device +		+  SSI protocol  +
	+  (omap_ssi.pX-cY)   +	<-------+  driver        +
	+---------------------+		+----------------+
		|				|
(/sys/bus/ssi/devices/omap_ssi.pX-cy)	(/sys/bus/ssi/drivers/ssi_protocol)
		|				|
+---------------------------------------------------------------+
+			SSI bus					 +
+---------------------------------------------------------------+

			Figure 1.

(NOTE: omap_ssi.pX-cY represents the SSI channel Y on port X from the omap_ssi
device)

B) Data transfers

The OMAP SSI driver exports an asynchronous interface for sending and receiving
data over the SSI channels. Protocol drivers will register a set of read and write
completion callbacks for each SSI channel they use.

Protocol drivers call ssi_write/ssi_read functions to signal the OMAP SSI driver
that is willing to write/read data to/from a channel. Transfers are completed only
when the OMAP SSI driver calls the completion callback.

An SSI channel can simultaneously have both a read and a write request
pending, however, requests cannot be queued.

It is safe to call ssi_write/ssi_read functions inside the callbacks functions.
In fact, a protocol driver should normally re-issue the read request from within
the read callback, in order to not miss any incoming messages.

C) Error handling

SSI is a multi channel interface but the channels share the same physical wires.
Therefore, any transmission error potentially affects all the protocol drivers
that sit on top of the SSI driver. Whenever an error occurs, it is broadcasted to
all protocol drivers.

Errors are signaled to the protocol drivers through the port_event callback.

Completion callbacks functions are only called when a transfer has succeed.

II OMAP SSI API's
-----------------

A) Include

#include<linux/ssi_driver_if.h>

B) int register_ssi_driver(struct ssi_device_driver *driver);

Description: Register an SSI protocol driver

Parameter: A protocol driver declaration (see struct ssi_device_driver)

B) void unregister_ssi_driver(struct ssi_device_driver *driver);

Description: Unregister an SSI protocol driver

Parameter: A protocol driver declaration (see struct ssi_device_driver)

C) int ssi_open(struct ssi_device *dev);

Description: Open an SSI device channel

Parameter: The SSI channel

D) int ssi_write(struct ssi_device *dev, u32 *data, unsigned int count);

Description: Send data through an SSI channel. The transfer is only completed
when the write_complete callback is called

Parameters:
	- dev: SSI channel
	- data: pointer to the data to send
	- count: number of 32-bit words to be sent

E) void ssi_write_cancel(struct ssi_device *dev);

Description: Cancel current pending write operation

Parameters: SSI channel

F) int ssi_read(struct ssi_device *dev, u32 *data, unsigned int w_count);

Description: Receive data through an SSI channel. The transfer is only completed
when the read_complete callback is called

Parameters:
	- dev: SSI channel
	- data: pointer where to store the data
	- count: number of 32-bit words to be read


G) void ssi_read_cancel(struct ssi_device *dev);

Description: Cancel current pending read operation

Parameters: SSI channel

H) int ssi_ioctl(struct ssi_device *dev, unsigned int command, void *arg);

Description: Apply some control command to the port associated to the given
SSI channel

Parameters:
	- dev: SSI channel
	- command: command to execute
	- arg: parameter for the control command

Commands:
	- SSI_IOCTL_WAKE_UP:
		Description: Set SSI wakeup line for the channel
		Parameters: None
	- SSI_IOCTL_WAKE_DOWN:
		Description: Unset SSI wakeup line for the channel
		Parameters: None
	- SSI_IOCTL_SEND_BREAK:
		Description: Send a HW BREAK frame in FRAME mode
		Parameters: None
	- SSI_IOCTL_WAKE:
		Description: Get wakeup line status
		Parameters: Pointer to a u32 variable to return result
		(Result: 0 means wakeline DOWN, other result means wakeline UP)

I)void ssi_close(struct ssi_device *dev);

Description: Close an SSI channel

Parameters: The SSI channel to close

J) void ssi_dev_set_cb(	struct ssi_device *dev,
			void (*r_cb)(struct ssi_device *dev),
			void (*w_cb)(struct ssi_device *dev));

Description: Set the read and write callbacks for the SSI channel. This
function is usually called in the probe function of the SSI protocol driver to
set completion callbacks for the asynchronous read and write transfer

Parameters:
	- dev: SSI channel
	- r_cb: Pointer to a callback function to signal that a read transfer is
		completed
	- w_cb: Pointer to a callback function to signal that a write transfer
		is completed

H) struct ssi_device_driver

Description: Protocol drivers pass this struct to the register_ssi_driver function
in order to register with the OMAP SSI driver. Among other things it tells the
OMAP SSI driver which channels the protocol driver wants to allocate for its use

Declaration:
struct ssi_device_driver {
	unsigned long		ctrl_mask;
	unsigned long		ch_mask[SSI_MAX_PORTS];
	void 			(*port_event) (int c_id, unsigned int port,
						unsigned int event, void *arg);
	int			(*probe)(struct ssi_device *dev);
	int			(*remove)(struct ssi_device *dev);
	int			(*suspend)(struct ssi_device *dev,
						pm_message_t mesg);
	int			(*resume)(struct ssi_device *dev);
	struct device_driver 	driver;
};

Fields description:
	ctrl_mask: SSI block ids to use
	ch_mask[SSI_MAX_PORTS]: SSI channels to use
	port_event: Function callback for notifying SSI events
		   (i.e.: error transfer)
		Parameters:
			c_id: SSI Block id which generate the event
			port: Port number which generate the event
			event: Event code
	probe: Probe function
		Parameters: SSI channel
	remove: Remove function
		Parameters: SSI channel

Example:

static struct ssi_device_driver ssi_protocol_driver = {
	.ctrl_mask = ANY_SSI_CONTROLLER,
	.ch_mask[0] = CHANNEL(0) | CHANNEL(1),
	.port_event = port_event_callback,
	.probe = ssi_proto_probe,
	.remove = __devexit_p(ssi_proto_remove),
	.driver = {
			.name = "ssi_protocol",
	},
};


III OMAP SSI platform_device
----------------------------

[TBD] Explain interface to configure the ssi device controller.

=================================================
Contact: Carlos Chinea <carlos.chinea@nokia.com>
Copyright (C) 2008 Nokia Corporation.
