![]() |
|
|||
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
[ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
![]() ![]() |