Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:13

0001 /**
0002  * @file
0003  *
0004  * @ingroup libi2c
0005  *
0006  * @brief Legacy I2C Library
0007  */
0008 
0009 #ifndef _RTEMS_LIBI2C_H
0010 #define _RTEMS_LIBI2C_H
0011 
0012 /*
0013  * Authorship
0014  * ----------
0015  * This software was created by
0016  *     Till Straumann <strauman@slac.stanford.edu>, 2005,
0017  *     Stanford Linear Accelerator Center, Stanford University.
0018  *
0019  * Acknowledgement of sponsorship
0020  * ------------------------------
0021  * This software was produced by
0022  *     the Stanford Linear Accelerator Center, Stanford University,
0023  *     under Contract DE-AC03-76SFO0515 with the Department of Energy.
0024  *
0025  * Government disclaimer of liability
0026  * ----------------------------------
0027  * Neither the United States nor the United States Department of Energy,
0028  * nor any of their employees, makes any warranty, express or implied, or
0029  * assumes any legal liability or responsibility for the accuracy,
0030  * completeness, or usefulness of any data, apparatus, product, or process
0031  * disclosed, or represents that its use would not infringe privately owned
0032  * rights.
0033  *
0034  * Stanford disclaimer of liability
0035  * --------------------------------
0036  * Stanford University makes no representations or warranties, express or
0037  * implied, nor assumes any liability for the use of this software.
0038  *
0039  * Stanford disclaimer of copyright
0040  * --------------------------------
0041  * Stanford University, owner of the copyright, hereby disclaims its
0042  * copyright and all other rights in this software.  Hence, anyone may
0043  * freely use it for any purpose without restriction.
0044  *
0045  * Maintenance of notices
0046  * ----------------------
0047  * In the interest of clarity regarding the origin and status of this
0048  * SLAC software, this and all the preceding Stanford University notices
0049  * are to remain affixed to any copy or derivative of this software made
0050  * or distributed by the recipient and are to be affixed to any copy of
0051  * software made or distributed by the recipient that contains a copy or
0052  * derivative of this software.
0053  *
0054  * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03
0055  */
0056 
0057 #include <rtems.h>
0058 
0059 #include <rtems/io.h>
0060 
0061 #ifdef __cplusplus
0062 extern "C" {
0063 #endif
0064 
0065 /**
0066  * @defgroup libi2c Legacy I2C Library
0067  *
0068  * @ingroup RTEMSDeviceDrivers
0069  *
0070  * @brief Legacy I2C library.
0071  *
0072  */
0073 /**@{**/
0074 
0075 /* Simple I2C driver API */
0076 
0077 /* Initialize the libary - may fail if no semaphore or no driver slot is available */
0078 extern int rtems_libi2c_initialize (void);
0079 
0080 /* Alternatively to rtems_libi2c_initialize() the library can also be
0081  * initialized by means of a traditional driver table entry containing
0082  * the following entry points:
0083  */
0084 extern rtems_status_code
0085 rtems_i2c_init (
0086     rtems_device_major_number major,
0087     rtems_device_minor_number minor,
0088     void *arg);
0089 
0090 extern rtems_status_code
0091 rtems_i2c_open (
0092     rtems_device_major_number major,
0093     rtems_device_minor_number minor,
0094     void *arg);
0095 
0096 extern rtems_status_code
0097 rtems_i2c_close (
0098     rtems_device_major_number major,
0099     rtems_device_minor_number minor,
0100     void *arg);
0101 
0102 extern rtems_status_code
0103 rtems_i2c_read (
0104     rtems_device_major_number major,
0105     rtems_device_minor_number minor,
0106     void *arg);
0107 
0108 extern rtems_status_code
0109 rtems_i2c_write (
0110     rtems_device_major_number major,
0111     rtems_device_minor_number minor,
0112     void *arg);
0113 
0114 extern rtems_status_code
0115 rtems_i2c_ioctl (
0116     rtems_device_major_number major,
0117     rtems_device_minor_number minor,
0118     void *arg);
0119 
0120 extern const rtems_driver_address_table rtems_libi2c_io_ops;
0121 
0122 /* Unfortunately, if you want to add this driver to
0123  * a RTEMS configuration table then you need all the
0124  * members explicitly :-( (Device_driver_table should
0125  * hold pointers to rtems_driver_address_tables rather
0126  * than full structs).
0127  *
0128  * The difficulty is that adding this driver to the
0129  * configuration table is not enough; you still need
0130  * to populate the framework with low-level bus-driver(s)
0131  * and high-level drivers and/or device-files...
0132  *
0133  * Currently the preferred way is having the BSP
0134  * call 'rtems_libi2c_initialize' followed by
0135  * 'rtems_libi2c_register_bus' and
0136  * 'rtems_libi2c_register_drv' and/or
0137  * 'mknod' (for 'raw' device nodes)
0138  * from the 'bsp_predriver_hook'.
0139  */
0140 #define RTEMS_LIBI2C_DRIVER_TABLE_ENTRY   \
0141 {                                         \
0142   initialization_entry:  rtems_i2c_init,  \
0143   open_entry:            rtems_i2c_open,  \
0144   close_entry:           rtems_i2c_close, \
0145   read_entry:            rtems_i2c_read,  \
0146   write_entry:           rtems_i2c_write, \
0147   control_entry:         rtems_i2c_ioctl, \
0148 }
0149 
0150 /* Bus Driver API
0151  *
0152  * Bus drivers provide access to low-level i2c functions
0153  * such as 'send start', 'send address', 'get bytes' etc.
0154  */
0155 
0156 /* first field must be a pointer to ops; driver
0157  * may add its own fields after this.
0158  * the struct that is registered with the library
0159  * is not copied; a pointer will we passed
0160  * to the callback functions (ops).
0161  */
0162 typedef struct rtems_libi2c_bus_t_
0163 {
0164   const struct rtems_libi2c_bus_ops_ *ops;
0165   int size;                     /* size of whole structure */
0166 } rtems_libi2c_bus_t;
0167 
0168 /* Access functions a low level driver must provide;
0169  *
0170  * All of these, except read_bytes and write_bytes
0171  * return RTEMS_SUCCESSFUL on success and an error status
0172  * otherwise. The read and write ops return the number
0173  * of chars read/written or -(status code) on error.
0174  */
0175 typedef struct rtems_libi2c_bus_ops_
0176 {
0177   /* Initialize the bus; might be called again to reset the bus driver */
0178   rtems_status_code (*init) (rtems_libi2c_bus_t * bushdl);
0179   /* Send start condition */
0180   rtems_status_code (*send_start) (rtems_libi2c_bus_t * bushdl);
0181   /* Send stop  condition */
0182   rtems_status_code (*send_stop) (rtems_libi2c_bus_t * bushdl);
0183   /* initiate transfer from (rw!=0) or to a device */
0184   rtems_status_code (*send_addr) (rtems_libi2c_bus_t * bushdl,
0185                                   uint32_t addr, int rw);
0186   /* read a number of bytes */
0187   int (*read_bytes) (rtems_libi2c_bus_t * bushdl, unsigned char *bytes,
0188                      int nbytes);
0189   /* write a number of bytes */
0190   int (*write_bytes) (rtems_libi2c_bus_t * bushdl, unsigned char *bytes,
0191                       int nbytes);
0192   /* ioctl misc functions */
0193   int (*ioctl) (rtems_libi2c_bus_t * bushdl,
0194         int   cmd,
0195         void *buffer
0196         );
0197 } rtems_libi2c_bus_ops_t;
0198 
0199 
0200 /*
0201  * Register a lowlevel driver
0202  *
0203  * TODO: better description
0204  *
0205  * This  allocates a major number identifying *this* driver
0206  * (i.e., libi2c) and the minor number encodes a bus# and a i2c address.
0207  *
0208  * The name will be registered in the filesystem (parent
0209  * directories must exist, also IMFS filesystem must exist). It may be NULL in
0210  * which case the library will pick a default.
0211  *
0212  * RETURNS: bus # (>=0) or -1 on error (errno set).
0213  */
0214 
0215 extern int rtems_libi2c_register_bus (const char *name, rtems_libi2c_bus_t * bus);
0216 
0217 extern rtems_device_major_number rtems_libi2c_major;
0218 
0219 #define RTEMS_LIBI2C_MAKE_MINOR(busno, i2caddr) \
0220     ((((busno)&((1<<3)-1))<<10) | ((i2caddr)&((1<<10)-1)))
0221 
0222 /* After the library is initialized, a major number is available.
0223  * As soon as a low-level bus driver is registered (above routine
0224  * returns a 'busno'), a device node can be created in the filesystem
0225  * with a major/minor number pair of
0226  *
0227  *    rtems_libi2c_major / RTEMS_LIBI2C_MAKE_MINOR(busno, i2caddr)
0228  *
0229  * and a 'raw' hi-level driver is then attached to this device
0230  * node.
0231  * This 'raw' driver has very simple semantics:
0232  *
0233  *   'open'         sends a start condition
0234  *   'read'/'write' address the device identified by the i2c bus# and address
0235  *                  encoded in the minor number and read or write, respectively
0236  *                  a stream of bytes from or to the device. Every time the
0237  *                  direction is changed, a 're-start' condition followed by
0238  *                  an 'address' cycle is generated on the i2c bus.
0239  *   'close'        sends a stop condition.
0240  *
0241  * Hence, using the 'raw' driver, e.g., 100 bytes at offset 0x200 can be
0242  * read from an EEPROM by the following pseudo-code:
0243  *
0244  *   mknod("/dev/i2c-54", mode, MKDEV(rtems_libi2c_major, RTEMS_LIBI2C_MAKE_MINOR(0,0x54)))
0245  *
0246  *   int fd;
0247  *   char off[2]={0x02,0x00};
0248  *
0249  *   fd = open("/dev/i2c-54",O_RDWR);
0250  *   write(fd,off,2);
0251  *   read(fd,buf,100);
0252  *   close(fd);
0253  *
0254  */
0255 
0256 /* Higher Level Driver API
0257  *
0258  * Higher level drivers know how to deal with specific i2c
0259  * devices (independent of the bus interface chip) and provide
0260  * an abstraction, i.e., the usual read/write/ioctl access.
0261  *
0262  * Using the above example, such a high level driver could
0263  * prevent the user from issuing potentially destructive write
0264  * operations (the aforementioned EEPROM interprets any 3rd
0265  * and following byte written to the device as data, i.e., the
0266  * contents could easily be changed!).
0267  * The correct 'read-pointer offset' programming could be
0268  * implemented in 'open' and 'ioctl' of a high-level driver and
0269  * the user would then only have to perform harmless read
0270  * operations, e.g.,
0271  *
0272  *    fd = open("/dev/i2c.eeprom",O_RDONLY) / * opens and sets EEPROM read pointer * /
0273  *    ioctl(fd, IOCTL_SEEK, 0x200)          / * repositions the read pointer       * /
0274  *    read(fd, buf, 100)
0275  *    close(fd)
0276  *
0277  */
0278 
0279 /* struct provided at driver registration. The driver may store
0280  * private data behind the mandatory first fields but the size
0281  * must be set to the size of the entire struct, e.g.,
0282  *
0283  * struct driver_pvt {
0284  *  rtems_libi2c_drv_t pub;
0285  *  struct {  ...    } pvt;
0286  * } my_driver = {
0287  *      {  ops: my_ops,
0288  *        size: sizeof(my_driver)
0289  *      },
0290  *      { ...};
0291  * };
0292  *
0293  * A pointer to this struct is passed to the callback ops.
0294  */
0295 
0296 typedef struct rtems_libi2c_drv_t_
0297 {
0298   const rtems_driver_address_table *ops;      /* the driver ops */
0299   int size;                     /* size of whole structure (including appended private data) */
0300 } rtems_libi2c_drv_t;
0301 
0302 /*
0303  * The high level driver must be registered with a particular
0304  * bus number and i2c address.
0305  *
0306  * The registration procedure also creates a filesystem node,
0307  * i.e., the returned minor number is not really needed.
0308  *
0309  * If the 'name' argument is NULL, no filesystem node is
0310  * created (but this can be done 'manually' using rtems_libi2c_major
0311  * and the return value of this routine).
0312  *
0313  * RETURNS minor number (FYI) or -1 on failure
0314  */
0315 extern int
0316 rtems_libi2c_register_drv (const char *name, rtems_libi2c_drv_t * drvtbl,
0317                            unsigned bus, unsigned i2caddr);
0318 
0319 /* Operations available to high level drivers */
0320 
0321 /* NOTES: The bus a device is attached to is LOCKED from the first send_start
0322  *        until send_stop is executed!
0323  *
0324  *        Bus tenure MUST NOT span multiple system calls - otherwise, a single
0325  *        thread could get into the protected sections (or would deadlock if the
0326  *        mutex was not nestable).
0327  *        E.g., consider what happens if 'open' sends a 'start' and 'close'
0328  *        sends a 'stop' (i.e., the bus mutex would be locked in 'open' and
0329  *        released in 'close'. A single thread could try to open two devices
0330  *        on the same bus and would either deadlock or nest into the bus mutex
0331  *        and potentially mess up the i2c messages.
0332  *
0333  *        The correct way is to *always* relinquish the i2c bus (i.e., send 'stop'
0334  *        from any driver routine prior to returning control to the caller.
0335  *        Consult the implementation of the generic driver routines (open, close, ...)
0336  *        below or the examples in i2c-2b-eeprom.c and i2c-2b-ds1621.c
0337  *
0338  * Drivers just pass the minor number on to these routines...
0339  */
0340 extern rtems_status_code rtems_libi2c_send_start (rtems_device_minor_number minor);
0341 
0342 extern rtems_status_code rtems_libi2c_send_stop (rtems_device_minor_number minor);
0343 
0344 extern rtems_status_code
0345 rtems_libi2c_send_addr (rtems_device_minor_number minor, int rw);
0346 
0347 /* the read/write routines return the number of bytes transferred
0348  * or -(status_code) on error.
0349  */
0350 extern int
0351 rtems_libi2c_read_bytes (rtems_device_minor_number minor,
0352                          unsigned char *bytes, int nbytes);
0353 
0354 extern int
0355 rtems_libi2c_write_bytes (rtems_device_minor_number minor,
0356                           const unsigned char *bytes, int nbytes);
0357 
0358 /* Send start, send address and read bytes */
0359 extern int
0360 rtems_libi2c_start_read_bytes (rtems_device_minor_number minor,
0361                    unsigned char *bytes,
0362                                int nbytes);
0363 
0364 /* Send start, send address and write bytes */
0365 extern int
0366 rtems_libi2c_start_write_bytes (rtems_device_minor_number minor,
0367                 const unsigned char *bytes,
0368                                 int nbytes);
0369 
0370 
0371 /* call misc iocontrol function */
0372 extern int
0373 rtems_libi2c_ioctl (rtems_device_minor_number minor,
0374             int cmd,
0375             ...);
0376 /*
0377  * NOTE: any low-level driver ioctl returning a negative
0378  * result for release the bus (perform a STOP condition)
0379  */
0380 /*******************************
0381  * defined IOCTLs:
0382  *******************************/
0383 #define RTEMS_LIBI2C_IOCTL_READ_WRITE  1
0384 /*
0385  * retval = rtems_libi2c_ioctl(rtems_device_minor_number minor,
0386  *                             RTEMS_LIBI2C_IOCTL_READ_WRITE,
0387  *                              rtems_libi2c_read_write_t *arg);
0388  *
0389  * This call performs a simultanous read/write transfer,
0390  * which is possible (and sometimes needed) for SPI devices
0391  *
0392  *   arg is a pointer to a rd_wr info data structure
0393  *
0394  * This call is only needed for SPI devices
0395  */
0396 #define RTEMS_LIBI2C_IOCTL_START_TFM_READ_WRITE  2
0397 /*
0398  * retval = rtems_libi2c_ioctl(rtems_device_minor_number minor,
0399  *                             RTEMS_LIBI2C_IOCTL_START_READ_WRITE,
0400  *                             unsigned char *rd_buffer,
0401  *                             const unsigned char *wr_buffer,
0402  *                             int byte_cnt,
0403  *                             const rtems_libi2c_tfr_mode_t *tfr_mode_ptr);
0404  *
0405  * This call addresses a slave and then:
0406  * - sets the proper transfer mode,
0407  *  - performs a simultanous  read/write transfer,
0408  *    (which is possible and sometimes needed for SPI devices)
0409  *    NOTE: - if rd_buffer is NULL, receive data will be dropped
0410  *          - if wr_buffer is NULL, bytes with content 0 will transmitted
0411  *
0412  *   rd_buffer is a pointer to a receive buffer (or NULL)
0413  *   wr_buffer is a pointer to the data to be sent (or NULL)
0414  *
0415  * This call is only needed for SPI devices
0416  */
0417 
0418 #define RTEMS_LIBI2C_IOCTL_SET_TFRMODE 3
0419 /*
0420  * retval = rtems_libi2c_ioctl(rtems_device_minor_number minor,
0421  *                             RTEMS_LIBI2C_IOCTL_SET_TFRMODE,
0422  *                             const rtems_libi2c_tfr_mode_t *tfr_mode_ptr);
0423  *
0424  * This call sets an SPI device to the transfer mode needed (baudrate etc.)
0425  *
0426  *   tfr_mode is a pointer to a structure defining the SPI transfer mode needed
0427  *   (see below).
0428  *
0429  * This call is only needed for SPI devices
0430  */
0431 
0432 #define RTEMS_LIBI2C_IOCTL_GET_DRV_T 4
0433 
0434 /*
0435  * retval = rtems_libi2c_ioctl(rtems_device_minor_number minor,
0436  *                             RTEMS_LIBI2C_IOCTL_GET_DRV_T,
0437  *                             const rtems_libi2c_drv_t *drv_t_ptr);
0438  *
0439  * This call allows the a high-level driver to query its driver table entry,
0440  * including its private data appended to it during creation of the entry
0441  *
0442  */
0443 
0444 /**
0445  * @brief IO control command for asynchronous read and write.
0446  *
0447  * @see rtems_libi2c_read_write_done_t and rtems_libi2c_read_write_async_t.
0448  *
0449  * @warning This is work in progress!
0450  */
0451 #define RTEMS_LIBI2C_IOCTL_READ_WRITE_ASYNC 5
0452 
0453 /*
0454  * argument data structures for IOCTLs defined above
0455  */
0456 typedef struct {
0457   unsigned char       *rd_buf;
0458   const unsigned char *wr_buf;
0459   int                  byte_cnt;
0460 } rtems_libi2c_read_write_t;
0461 
0462 typedef struct {
0463   uint32_t baudrate;       /* maximum bits per second               */
0464                            /* only valid for SPI drivers:           */
0465   uint8_t  bits_per_char;  /* how many bits per byte/word/longword? */
0466   bool     lsb_first;      /* true: send LSB first                  */
0467   bool     clock_inv;      /* true: inverted clock (high active)    */
0468   bool     clock_phs;      /* true: clock starts toggling at start of data tfr */
0469   uint32_t  idle_char;     /* This character will be continuously transmitted in read only functions */
0470 } rtems_libi2c_tfr_mode_t;
0471 
0472 typedef struct {
0473   rtems_libi2c_tfr_mode_t   tfr_mode;
0474   rtems_libi2c_read_write_t rd_wr;
0475 } rtems_libi2c_tfm_read_write_t;
0476 
0477 /**
0478  * @brief Notification function type for asynchronous read and write.
0479  *
0480  * @see RTEMS_LIBI2C_IOCTL_READ_WRITE_ASYNC and
0481  * rtems_libi2c_read_write_async_t.
0482  *
0483  * @warning This is work in progress!
0484  */
0485 typedef void (*rtems_libi2c_read_write_done_t) \
0486   ( int /* return value */, int /* nbytes */, void * /* arg */);
0487 
0488 /**
0489  * @brief IO command data for asynchronous read and write.
0490  *
0491  * @see RTEMS_LIBI2C_IOCTL_READ_WRITE_ASYNC and
0492  * rtems_libi2c_read_write_done_t.
0493  *
0494  * @warning This is work in progress!
0495  */
0496 typedef struct {
0497   unsigned char                 *rd_buf;
0498   const unsigned char           *wr_buf;
0499   int                            byte_cnt;
0500   rtems_libi2c_read_write_done_t done;
0501   void                          *arg;
0502 } rtems_libi2c_read_write_async_t;
0503 
0504 /** @} */
0505 
0506 #ifdef __cplusplus
0507 }
0508 #endif
0509 
0510 #endif