source: rtems/cpukit/libi2c/libi2c.h @ 797c232

4.104.114.9
Last change on this file since 797c232 was d2ff24c2, checked in by Till Straumann <strauman@…>, on Nov 21, 2007 at 6:20:49 AM

2007-11-17 Till Straumann <strauman@…>

  • libi2c/libi2c.c, libi2c/libi2c.h, libi2c/README_libi2c: Added checks so that use of 'stdio' is avoided (falling back to 'printk') before the system is up. Publish driver entry points so that the libi2c driver could be added to the applications 'device driver table'. This is not fully implemented yet, though, since in addition to initializing libi2c the low-level i2c bus drivers as well as high-level i2c device drivers need to be registered with the library. Updated README_libi2c accordingly.
  • Property mode set to 100644
File size: 14.9 KB
Line 
1#ifndef RTEMS_LIBI2C_H
2#define RTEMS_LIBI2C_H
3/*$Id$*/
4
5/*
6 * Authorship
7 * ----------
8 * This software was created by
9 *     Till Straumann <strauman@slac.stanford.edu>, 2005,
10 *         Stanford Linear Accelerator Center, Stanford University.
11 *
12 * Acknowledgement of sponsorship
13 * ------------------------------
14 * This software was produced by
15 *     the Stanford Linear Accelerator Center, Stanford University,
16 *         under Contract DE-AC03-76SFO0515 with the Department of Energy.
17 *
18 * Government disclaimer of liability
19 * ----------------------------------
20 * Neither the United States nor the United States Department of Energy,
21 * nor any of their employees, makes any warranty, express or implied, or
22 * assumes any legal liability or responsibility for the accuracy,
23 * completeness, or usefulness of any data, apparatus, product, or process
24 * disclosed, or represents that its use would not infringe privately owned
25 * rights.
26 *
27 * Stanford disclaimer of liability
28 * --------------------------------
29 * Stanford University makes no representations or warranties, express or
30 * implied, nor assumes any liability for the use of this software.
31 *
32 * Stanford disclaimer of copyright
33 * --------------------------------
34 * Stanford University, owner of the copyright, hereby disclaims its
35 * copyright and all other rights in this software.  Hence, anyone may
36 * freely use it for any purpose without restriction. 
37 *
38 * Maintenance of notices
39 * ----------------------
40 * In the interest of clarity regarding the origin and status of this
41 * SLAC software, this and all the preceding Stanford University notices
42 * are to remain affixed to any copy or derivative of this software made
43 * or distributed by the recipient and are to be affixed to any copy of
44 * software made or distributed by the recipient that contains a copy or
45 * derivative of this software.
46 *
47 * ------------------ SLAC Software Notices, Set 4 OTT.002a, 2004 FEB 03
48 */ 
49
50#include <rtems.h>
51
52#include <rtems/io.h>
53
54#ifdef __cplusplus
55extern "C" {
56#endif
57
58/* Simple I2C driver API */
59
60/* Initialize the libary - may fail if no semaphore or no driver slot is available */
61int rtems_libi2c_initialize ();
62
63/* Alternatively to rtems_libi2c_initialize() the library can also be
64 * initialized by means of a traditional driver table entry containing
65 * the following entry points:
66 */
67rtems_status_code
68rtems_i2c_init (
69        rtems_device_major_number major,
70        rtems_device_minor_number minor,
71    void *arg);
72
73rtems_status_code
74rtems_i2c_open (
75        rtems_device_major_number major,
76        rtems_device_minor_number minor,
77    void *arg);
78
79rtems_status_code
80rtems_i2c_close (
81        rtems_device_major_number major,
82        rtems_device_minor_number minor,
83    void *arg);
84
85rtems_status_code
86rtems_i2c_read (
87        rtems_device_major_number major,
88        rtems_device_minor_number minor,
89    void *arg);
90
91rtems_status_code
92rtems_i2c_write (
93        rtems_device_major_number major,
94        rtems_device_minor_number minor,
95    void *arg);
96
97rtems_status_code
98rtems_i2c_ioctl (
99        rtems_device_major_number major,
100        rtems_device_minor_number minor,
101    void *arg);
102
103extern rtems_driver_address_table rtems_libi2c_io_ops;
104
105/* Unfortunately, if you want to add this driver to
106 * a RTEMS configuration table then you need all the
107 * members explicitly :-( (Device_driver_table should
108 * hold pointers to rtems_driver_address_tables rather
109 * than full structs).
110 *
111 * The difficulty is that adding this driver to the
112 * configuration table is not enough; you still need
113 * to populate the framework with low-level bus-driver(s)
114 * and high-level drivers and/or device-files...
115 *
116 * Currently the preferred way is having the BSP
117 * call 'rtems_libi2c_initialize' followed by
118 * 'rtems_libi2c_register_bus' and
119 * 'rtems_libi2c_register_drv' and/or
120 * 'mknod' (for 'raw' device nodes)
121 * from the 'pretasking_hook'.
122 */
123#define RTEMS_LIBI2C_DRIVER_TABLE_ENTRY   \
124{                                         \
125  initialization_entry:  rtems_i2c_init,  \
126  open_entry:            rtems_i2c_open,  \
127  close_entry:           rtems_i2c_close, \
128  read_entry:            rtems_i2c_read,  \
129  write_entry:           rtems_i2c_write, \
130  control_entry:         rtems_i2c_ioctl, \
131}
132
133/* Bus Driver API
134 *
135 * Bus drivers provide access to low-level i2c functions
136 * such as 'send start', 'send address', 'get bytes' etc.
137 */
138
139/* first field must be a pointer to ops; driver
140 * may add its own fields after this.
141 * the struct that is registered with the library
142 * is not copied; a pointer will we passed
143 * to the callback functions (ops).
144 */
145typedef struct rtems_libi2c_bus_t_
146{
147  struct rtems_libi2c_bus_ops_ *ops;
148  int size;                     /* size of whole structure */
149} rtems_libi2c_bus_t;
150
151/* Access functions a low level driver must provide;
152 *
153 * All of these, except read_bytes and write_bytes
154 * return RTEMS_SUCCESSFUL on success and an error status
155 * otherwise. The read and write ops return the number
156 * of chars read/written or -(status code) on error.
157 */
158typedef struct rtems_libi2c_bus_ops_
159{
160  /* Initialize the bus; might be called again to reset the bus driver */
161  rtems_status_code (*init) (rtems_libi2c_bus_t * bushdl);
162  /* Send start condition */
163  rtems_status_code (*send_start) (rtems_libi2c_bus_t * bushdl);
164  /* Send stop  condition */
165  rtems_status_code (*send_stop) (rtems_libi2c_bus_t * bushdl);
166  /* initiate transfer from (rw!=0) or to a device */
167  rtems_status_code (*send_addr) (rtems_libi2c_bus_t * bushdl,
168                                  uint32_t addr, int rw);
169  /* read a number of bytes */
170  int (*read_bytes) (rtems_libi2c_bus_t * bushdl, unsigned char *bytes,
171                     int nbytes);
172  /* write a number of bytes */
173  int (*write_bytes) (rtems_libi2c_bus_t * bushdl, unsigned char *bytes,
174                      int nbytes);
175  /* ioctl misc functions */
176  int (*ioctl) (rtems_libi2c_bus_t * bushdl, 
177                int   cmd,
178                void *buffer;
179                );
180} rtems_libi2c_bus_ops_t;
181
182
183/*
184 * Register a lowlevel driver
185 *
186 * TODO: better description
187 *
188 * This  allocates a major number identifying *this* driver
189 * (i.e., libi2c) and the minor number encodes a bus# and a i2c address.
190 *
191 * The name will be registered in the filesystem (parent
192 * directories must exist, also IMFS filesystem must exist see
193 * CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM). It may be NULL in which case
194 * the library will pick a default.
195 *
196 * RETURNS: bus # (>=0) or -1 on error (errno set).
197 */
198
199int rtems_libi2c_register_bus (char *name, rtems_libi2c_bus_t * bus);
200
201extern rtems_device_major_number rtems_libi2c_major;
202
203#define RTEMS_LIBI2C_MAKE_MINOR(busno, i2caddr) \
204        ((((busno)&((1<<3)-1))<<10) | ((i2caddr)&((1<<10)-1)))
205
206/* After the library is initialized, a major number is available.
207 * As soon as a low-level bus driver is registered (above routine
208 * returns a 'busno'), a device node can be created in the filesystem
209 * with a major/minor number pair of
210 *
211 *    rtems_libi2c_major / RTEMS_LIBI2C_MAKE_MINOR(busno, i2caddr)
212 *
213 * and a 'raw' hi-level driver is then attached to this device
214 * node.
215 * This 'raw' driver has very simple semantics:
216 *
217 *   'open'         sends a start condition
218 *   'read'/'write' address the device identified by the i2c bus# and address
219 *                  encoded in the minor number and read or write, respectively
220 *                  a stream of bytes from or to the device. Every time the
221 *                  direction is changed, a 're-start' condition followed by
222 *                  an 'address' cycle is generated on the i2c bus.
223 *   'close'        sends a stop condition.
224 *
225 * Hence, using the 'raw' driver, e.g., 100 bytes at offset 0x200 can be
226 * read from an EEPROM by the following pseudo-code:
227 *
228 *   mknod("/dev/i2c-54", mode, MKDEV(rtems_libi2c_major, RTEMS_LIBI2C_MAKE_MINOR(0,0x54)))
229 *
230 *   int fd;
231 *   char off[2]={0x02,0x00};
232 *
233 *   fd = open("/dev/i2c-54",O_RDWR);
234 *   write(fd,off,2);
235 *   read(fd,buf,100);
236 *   close(fd);
237 *
238 */
239
240/* Higher Level Driver API
241 *
242 * Higher level drivers know how to deal with specific i2c
243 * devices (independent of the bus interface chip) and provide
244 * an abstraction, i.e., the usual read/write/ioctl access.
245 *
246 * Using the above example, such a high level driver could
247 * prevent the user from issuing potentially destructive write
248 * operations (the aforementioned EEPROM interprets any 3rd
249 * and following byte written to the device as data, i.e., the
250 * contents could easily be changed!).
251 * The correct 'read-pointer offset' programming could be
252 * implemented in 'open' and 'ioctl' of a high-level driver and
253 * the user would then only have to perform harmless read
254 * operations, e.g.,
255 *
256 *    fd = open("/dev/i2c.eeprom",O_RDONLY) / * opens and sets EEPROM read pointer * /
257 *    ioctl(fd, IOCTL_SEEK, 0x200)                      / * repositions the read pointer       * /
258 *    read(fd, buf, 100)
259 *    close(fd)
260 *
261 */
262
263/* struct provided at driver registration. The driver may store
264 * private data behind the mandatory first fields but the size
265 * must be set to the size of the entire struct, e.g.,
266 *
267 * struct driver_pvt {
268 *      rtems_libi2c_drv_t pub;
269 *      struct {  ...    } pvt;
270 * } my_driver = {
271 *              {  ops: my_ops,
272 *                size: sizeof(my_driver)
273 *              },
274 *              { ...};
275 * };
276 *
277 * A pointer to this struct is passed to the callback ops.
278 */
279
280typedef struct rtems_libi2c_drv_t_
281{
282  rtems_driver_address_table *ops;      /* the driver ops */
283  int size;                     /* size of whole structure (including appended private data) */
284} rtems_libi2c_drv_t;
285
286/*
287 * The high level driver must be registered with a particular
288 * bus number and i2c address.
289 *
290 * The registration procedure also creates a filesystem node,
291 * i.e., the returned minor number is not really needed.
292 *
293 * If the 'name' argument is NULL, no filesystem node is
294 * created (but this can be done 'manually' using rtems_libi2c_major
295 * and the return value of this routine).
296 *
297 * RETURNS minor number (FYI) or -1 on failure
298 */
299int
300rtems_libi2c_register_drv (char *name, rtems_libi2c_drv_t * drvtbl,
301                           unsigned bus, unsigned i2caddr);
302
303/* Operations available to high level drivers */
304
305/* NOTES: The bus a device is attached to is LOCKED from the first send_start
306 *        until send_stop is executed!
307 *
308 *        Bus tenure MUST NOT span multiple system calls - otherwise, a single
309 *        thread could get into the protected sections (or would deadlock if the
310 *                mutex was not nestable).
311 *                E.g., consider what happens if 'open' sends a 'start' and 'close'
312 *                sends a 'stop' (i.e., the bus mutex would be locked in 'open' and
313 *        released in 'close'. A single thread could try to open two devices
314 *        on the same bus and would either deadlock or nest into the bus mutex
315 *        and potentially mess up the i2c messages.
316 *
317 *        The correct way is to *always* relinquish the i2c bus (i.e., send 'stop'
318 *                from any driver routine prior to returning control to the caller.
319 *                Consult the implementation of the generic driver routines (open, close, ...)
320 *                below or the examples in i2c-2b-eeprom.c and i2c-2b-ds1621.c
321 *
322 * Drivers just pass the minor number on to these routines...
323 */
324rtems_status_code rtems_libi2c_send_start (rtems_device_minor_number minor);
325
326rtems_status_code rtems_libi2c_send_stop (rtems_device_minor_number minor);
327
328rtems_status_code
329rtems_libi2c_send_addr (rtems_device_minor_number minor, int rw);
330
331/* the read/write routines return the number of bytes transferred
332 * or -(status_code) on error.
333 */
334int
335rtems_libi2c_read_bytes (rtems_device_minor_number minor,
336                         unsigned char *bytes, int nbytes);
337
338int
339rtems_libi2c_write_bytes (rtems_device_minor_number minor,
340                          unsigned char *bytes, int nbytes);
341
342/* Send start, send address and read bytes */
343int
344rtems_libi2c_start_read_bytes (rtems_device_minor_number minor, 
345                               unsigned char *bytes,
346                               int nbytes);
347
348/* Send start, send address and write bytes */
349int
350rtems_libi2c_start_write_bytes (rtems_device_minor_number minor, 
351                                unsigned char *bytes,
352                                int nbytes);
353
354
355/* call misc iocontrol function */
356int
357rtems_libi2c_ioctl (rtems_device_minor_number minor,
358                    int cmd,
359                    ...);
360/*
361 * NOTE: any low-level driver ioctl returning a negative
362 * result for release the bus (perform a STOP condition)
363 */
364/*******************************
365 * defined IOCTLs:
366 *******************************/
367#define RTEMS_LIBI2C_IOCTL_READ_WRITE  1
368/*
369 * retval = rtems_libi2c_ioctl(rtems_device_minor_number minor,
370 *                             RTEMS_LIBI2C_IOCTL_READ_WRITE,
371 *                              rtems_libi2c_read_write_t *arg);
372 *
373 * This call performs a simultanous read/write transfer,
374 * which is possible (and sometimes needed) for SPI devices
375 *
376 *   arg is a pointer to a rd_wr info data structure
377 *
378 * This call is only needed for SPI devices
379 */
380#define RTEMS_LIBI2C_IOCTL_START_TFM_READ_WRITE  2
381/*
382 * retval = rtems_libi2c_ioctl(rtems_device_minor_number minor,
383 *                             RTEMS_LIBI2C_IOCTL_START_READ_WRITE,
384 *                             unsigned char *rd_buffer,
385 *                             const unsigned char *wr_buffer,
386 *                             int byte_cnt,
387 *                             const rtems_libi2c_tfr_mode_t *tfr_mode_ptr);
388 *
389 * This call addresses a slave and then:
390 * - sets the proper transfer mode,
391 *  - performs a simultanous  read/write transfer,
392 *    (which is possible and sometimes needed for SPI devices)
393 *    NOTE: - if rd_buffer is NULL, receive data will be dropped
394 *          - if wr_buffer is NULL, bytes with content 0 will transmitted
395 *
396 *   rd_buffer is a pointer to a receive buffer (or NULL)
397 *   wr_buffer is a pointer to the data to be sent (or NULL)
398 *
399 * This call is only needed for SPI devices
400 */
401
402#define RTEMS_LIBI2C_IOCTL_SET_TFRMODE 3
403/*
404 * retval = rtems_libi2c_ioctl(rtems_device_minor_number minor,
405 *                             RTEMS_LIBI2C_IOCTL_SET_TFRMODE,
406 *                             const rtems_libi2c_tfr_mode_t *tfr_mode_ptr);
407 *
408 * This call sets an SPI device to the transfer mode needed (baudrate etc.)
409 *
410 *   tfr_mode is a pointer to a structure defining the SPI transfer mode needed
411 *   (see below).
412 *
413 * This call is only needed for SPI devices
414 */
415
416/*
417 * arguemtn data structures for IOCTLs defined above
418 */
419typedef struct {
420  unsigned char       *rd_buf;
421  const unsigned char *wr_buf;
422  int                  byte_cnt;
423} rtems_libi2c_read_write_t;
424
425typedef struct {
426  uint32_t baudrate;       /* maximum bits per second               */
427                           /* only valid for SPI drivers:           */
428  uint8_t  bits_per_char;  /* how many bits per byte/word/longword? */
429  boolean  lsb_first;      /* TRUE: send LSB first                  */
430  boolean  clock_inv;      /* TRUE: inverted clock (high active)    */
431  boolean  clock_phs;      /* TRUE: clock starts toggling at start of data tfr */
432} rtems_libi2c_tfr_mode_t;
433
434typedef struct {
435  rtems_libi2c_tfr_mode_t   tfr_mode;
436  rtems_libi2c_read_write_t rd_wr;
437} rtems_libi2c_tfm_read_write_t;
438
439
440#ifdef __cplusplus
441}
442#endif
443
444#endif
Note: See TracBrowser for help on using the repository browser.