source: rtems/cpukit/libi2c/libi2c.h @ 2015ca6

4.104.114.95
Last change on this file since 2015ca6 was 2015ca6, checked in by Joel Sherrill <joel.sherrill@…>, on 05/13/08 at 20:37:36

2008-05-13 Robert S. Grimes <rsg@…>

  • libi2c/libi2c.h: Fix typo.
  • 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.