summaryrefslogtreecommitdiffstats
path: root/cpukit/libi2c/README_libi2c
diff options
context:
space:
mode:
Diffstat (limited to 'cpukit/libi2c/README_libi2c')
-rw-r--r--cpukit/libi2c/README_libi2c367
1 files changed, 367 insertions, 0 deletions
diff --git a/cpukit/libi2c/README_libi2c b/cpukit/libi2c/README_libi2c
new file mode 100644
index 0000000000..f1a8fd017e
--- /dev/null
+++ b/cpukit/libi2c/README_libi2c
@@ -0,0 +1,367 @@
+#
+# $Id$
+#
+
+=====================
+Copyright and License
+=====================
+
+For Copyright and License of the source code, see the header in
+libi2c.c.
+
+=========
+Overview
+========
+
+This directory contains a general I2C/SPI API library. It offers a
+standard API to I2C or SPI based device drivers, abstracting the low
+level driver (dealing with the I2C/SPI controller hardware of the
+board) from the high-level drivers (dealing with devices connected to
+the I2C or SPI bus).
+
+In most cases throughout this document, i2c and spi devices are
+handled in a similar way. Therefore spi will not be explicitly named
+in every location.
+
+=========
+Features
+=========
+
+ + supports multiple i2c and/or spi busses
+
+ + supports multiple devices connected to each i2c/spi bus
+
+ + handles bus and device registration to the I/O manager
+
+=========
+Structure
+=========
+
+This library defines a layered API to i2c and spi devices. The
+layering is:
+
+ +----------------------------------------+
+ 6| Application |
+ +----------------------------------------+
+ 5| RTEMS I/O Manager |
+ +----------------------------------------+
+ 4|** libi2c OS adaption layer **|
+ +----------------------------------------+
+ 3| high level i2c device driver |
+ | (EEPROM, RTC, ...) |
+ | (e.g. in c/src/libchip/i2c) |
+ +----------------------------------------+
+ 2|** libi2c low level abstraction layer **|
+ +----------------------------------------+
+ 1| i2c controller driver |
+ | (in BSP) |
+ +----------------------------------------+
+
+This document will describe the following interfaces in separate
+sections:
+
+ + the interface between the RTEMS I/O Manager and the libi2c OS
+ interface (5<->4)
+
+ + the interface between the libi2c OS interface and the high level
+ i2c device driver (4<->3)
+
+ + the interface between the high level i2c device driver and the
+ libi2c low level abstraction layer (3<->2)
+
+ + the interface between the libi2c low level abstraction layer and
+ the i2c controller driver (2<->1)
+
+===================================
+Differences between i2c and spi bus
+===================================
+SPI and I2C has many similarities, but also some differences:
+
+- I2C uses inband addressing (the first bits sent select, which slave
+device is addressed) while SPI uses dedicated select lines to address
+a slave device
+
+- SPI supports combined full duplex read-write transactions while I2C
+either sends or receives data from a slave device
+
+- SPI supports a varity of per-slave options, which include:
+ - number of bits per character to transfer
+ - polarity and phase of clock wrt data
+ - clock frequency
+
+The libi2c API defines a superset of functions to handle both flavours
+of serial data transmission, but care should be taken not to use
+features dedicated to the wrong type of serial bus.
+
+
+======================
+Library Initialization
+======================
+Before any libi2c API is used, the library must be initialized. This
+is achived with a call to function
+
+ rtems_libi2c_initialize ().
+
+It creates a global mutex to lock internal data structures and
+registers the OS adaption layer to the RTEMS I/O manager.
+
+Any subsequent call to this function will be silently ignored.
+
+Typically the BSP startup code will perform this initialization.
+
+A proper place for initializing the i2c layer and populating it
+with busses and device drivers (see 'Bus Registration' and
+'Device/Driver Registration' below) is the 'predriver_hook'
+where most facilities (such as malloc, libio) are already
+available. Note, however, that 'stdio' is not yet functional
+at this point and all i2c bus and device drivers should carefully
+avoid using stdio so that other drivers which may build on top
+of i2c devices may be initialized properly (this may happen
+just after 'predriver_hook' when stdio is still not available).
+E.g., drivers listed in the configuration table are initialized
+during this step.
+
+Note that while 'libi2c' could be initialized from the rtems
+configuration table like other drivers there is no easy
+way of populating the i2c framework with bus- and device-
+drivers at this point (unless a special 'i2c' configuration
+table describing the bus layout is implemented in the future).
+
+For the time being, we must rely on the BSP (predriver_hook)
+to initialize the i2c system if it is used by other drivers
+(e.g., the RTC driver may have to use a i2c device).
+
+===================
+Bus Registration
+===================
+Each i2c and/or spi bus available must be registerd with a call to
+
+int rtems_libi2c_register_bus (char *name,
+ rtems_libi2c_bus_t * bus)
+
+It registers the bus to the libi2c internal data structures and
+creates a device node in the RTEMS filesystem with the given name. If
+no name is given (name==NULL), then the default name "/dev/i2c" is
+used instead.
+
+With the second calling parameter "rtems_libi2c_bus_t * bus" the
+caller passes in a set of function pointers, which define the entries
+into the i2c controller driver (defined in the BSP).
+
+This call returns an integer bus number, which can be used in
+subsequent calls to register devices attached to this bus (see below).
+
+Typically the BSP startup code will perform this registration for each
+bus available on the board.
+
+==========================
+Device/Driver Registration
+==========================
+Each device attached to an i2c or spi bus must be registered with a
+call to
+
+int
+rtems_libi2c_register_drv (char *name, rtems_libi2c_drv_t * drvtbl,
+ unsigned bus, unsigned i2caddr);
+
+With this call, libi2c is informed, that:
+
+- a device is attached to the given "bus" number (which in fact is the
+return value received from a previous rtems_libi2c_register_bus()
+call) with the address "i2caddr"
+
+- the device is managed by a driver, who's entry functions are listed
+ in "drvtbl"
+
+- the device should be registered with the given "name" in the device
+ tree of the filesystem.
+
+The call will create a proper minor device number, which has the bus
+number and i2c_address encoded. This minor number is the return value
+of the call and is also associated with the filesystem node created
+for this device.
+
+Note: If you have multiple devices of the same type, you must register
+each of them through a separate call (with the same "drvtbl", but
+different name/bus/i2caddr).
+
+====================================================================
+(5<->4) RTEMS I/O Manager and the libi2c OS adaption layer IF
+====================================================================
+
+The RTEMS I/O Manager regards the libi2c OS adaption layer as a normal
+RTEMS Device Driver with one unique major number and a set of minor
+numbers, one for each bus and one for each device attached to one of
+the busses.
+
+Therefore the libi2c OS adaption layer provides the standard calls:
+
+static rtems_driver_address_table libi2c_io_ops = {
+ initialization_entry: i2c_init,
+ open_entry: i2c_open,
+ close_entry: i2c_close,
+ read_entry: i2c_read,
+ write_entry: i2c_write,
+ control_entry: i2c_ioctl
+};
+
+These calls perform some parameter checking and then call the
+appropriate high level i2c device driver function, if available,
+according to the entries in the "drvtbl" passed in the
+rtems_libi2c_register_drv() call.
+
+There are two exceptions: when i2c_read or i2c_write is called with a
+minor number specifying a bus (and not a device attached to the bus),
+then the respective transfer is performed as a raw byte stream
+transfer to the bus.
+
+The main reason for the libi2c OS adaption layer is, that it
+dispatches the RTEMS I/O Manager calls to the proper device driver
+according to the minor number used.
+
+====================================================================
+libi2c OS adaption layer and the high level i2c device driver IF
+====================================================================
+
+Each high level i2c device driver provides a set of functions in the
+rtems_libi2c_drv_t data structure passed the libi2c when the device is
+registered (see "Device registration" above). These function directly match
+the RTEMS I/O Mangers calls "open", "close", "read", "write",
+"control", and they are passed the same arguments. Functions not
+needed may be ommited (and replaced by a NULL pointer in
+rtems_libi2c_drv_t).
+
+======================================================================
+high level i2c device driver and libi2c low level abstraction layer IF
+======================================================================
+libi2c provides a set of functions for the high level drivers. These
+functions are:
+
+rtems_libi2c_send_start();
+rtems_libi2c_send_stop();
+rtems_libi2c_send_addr();
+rtems_libi2c_read_bytes();
+rtems_libi2c_write_bytes();
+rtems_libi2c_start_read_bytes();
+rtems_libi2c_start_write_bytes();
+rtems_libi2c_ioctl();
+
+Please look into libi2c.h for the proper parameters and return codes.
+
+These functions perform the proper i2c operations when called.
+
+A typical access sequence for the I2C bus would be:
+
+rtems_libi2c_send_start();
+rtems_libi2c_send_addr();
+rtems_libi2c_write_bytes();
+rtems_libi2c_send_stop();
+
+Alternatively, the rtems_libi2c_write_bytes() call could be relpaced
+with a
+ rtems_libi2c_read_bytes()
+
+call or a sequence of multiple calls.
+
+Note: rtems_libi2c_send_start() locks the i2c/spi bus used, so no other
+device can use this i2c/spi bus, until rtems_libi2c_send_stop() function
+is called for the same device.
+
+Special provisions for SPI devices:
+===================================
+For SPI devices and their drivers, the libi2c interface is used
+slightly differently:
+
+rtems_libi2c_send_start() will lock access to the SPI bus, but has no
+effect on the hardware bus interface.
+
+rtems_libi2c_ioctl(...,RTEMS_LIBI2C_IOCTL_SET_TFRMODE,...) will set
+the transfer mode (bit rate, clock phase and polaritiy, bits per
+char...) according to the rtems_libi2c_tfr_mode_t structure passed in.
+
+rtems_libi2c_send_addr() will activate the proper select line to
+address a certain SPI device. The correspondance between an address
+and the select line pulled is BSP specific.
+
+rtems_libi2c_send_stop(); will deactivate the address line and unlock
+the bus.
+
+A typical access sequence for the SPI bus would be:
+
+rtems_libi2c_send_start();
+rtems_libi2c_ioctl(...,RTEMS_LIBI2C_IOCTL_SET_TFRMODE,...);
+rtems_libi2c_send_addr();
+rtems_libi2c_write_bytes();
+rtems_libi2c_send_stop();
+
+Alternatively, the rtems_libi2c_write_bytes() call could be relpaced
+with a
+ rtems_libi2c_read_bytes()
+or a
+ rtems_libi2c_ioctl(...,RTEMS_LIBI2C_IOCTL_READ_WRITE,...)
+call or a sequence of multiple calls.
+
+====================================================================
+libi2c low level abstraction layer and i2c controller driver IF
+====================================================================
+Each low level i2c/spi driver must provide a set of bus_ops functions
+as defined in the rtems_libi2c_bus_ops_t structure.
+
+typedef struct rtems_libi2c_bus_ops_
+{
+ /* Initialize the bus; might be called again to reset the bus driver */
+ rtems_status_code (*init) (rtems_libi2c_bus_t * bushdl);
+ /* Send start condition */
+ rtems_status_code (*send_start) (rtems_libi2c_bus_t * bushdl);
+ /* Send stop condition */
+ rtems_status_code (*send_stop) (rtems_libi2c_bus_t * bushdl);
+ /* initiate transfer from (rw!=0) or to a device */
+ rtems_status_code (*send_addr) (rtems_libi2c_bus_t * bushdl,
+ uint32_t addr, int rw);
+ /* read a number of bytes */
+ int (*read_bytes) (rtems_libi2c_bus_t * bushdl, unsigned char *bytes,
+ int nbytes);
+ /* write a number of bytes */
+ int (*write_bytes) (rtems_libi2c_bus_t * bushdl, unsigned char *bytes,
+ int nbytes);
+ /* ioctl misc functions */
+ int (*ioctl) (rtems_libi2c_bus_t * bushdl,
+ int cmd,
+ void *buffer;
+ );
+} rtems_libi2c_bus_ops_t;
+
+Each of these functions performs the corresponding function to the i2c
+bus.
+
+Special provisions for SPI devices:
+===================================
+For SPI busses, special behaviour is required:
+
+(*send_start) (rtems_libi2c_bus_t * bushdl)
+ normally is an empty function.
+
+ (*send_addr) (rtems_libi2c_bus_t * bushdl, uint32_t addr, int rw)
+ will activate the SPI select line matching to addr.
+
+(*send_stop) (rtems_libi2c_bus_t * bushdl)
+ will deactivate the SPI select line
+
+(*ioctl(...,RTEMS_LIBI2C_IOCTL_SET_TFRMODE,...)
+ will set the transfer mode (bit rate, clock phase and
+ polaritiy, bits per char...) according to the
+ rtems_libi2c_tfr_mode_t structure passed in.
+
+(*ioctl(...,RTEMS_LIBI2C_IOCTL_READ_WRITE,...)
+ will send and receive data at the same time.
+
+Note:
+
+- low-level I2C drivers normally are specific to the master
+device, but independent from the board hardware. So in many cases they
+can totally reside in libcpu or libchip.
+
+- low-level SPI drivers are mostly board independent, but the
+ addressing is board/BSP dependent. Therefore the (*send_start),
+ (*send_addr) and (*send_stop) functions are typically defined in the
+ BSP. The rest of the functions can reside in libcpu or libchip.