source: rtems/cpukit/libi2c/libi2c.h @ c57316a

4.104.114.95
Last change on this file since c57316a was c57316a, checked in by Joel Sherrill <joel.sherrill@…>, on 10/11/07 at 12:46:50

2007-10-11 Daniel Hellstrom <daniel@…>

  • libi2c/libi2c.c, libi2c/libi2c.h: Add message about needing IMFS. Fixed check of status when registering driver. Add use of strerror().
  • Property mode set to 100644
File size: 9.8 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#include <rtems.h>
50
51#include <rtems/io.h>
52
53#ifdef __cplusplus
54extern "C" {
55#endif
56
57/* Simple I2C driver API */
58
59/* Initialize the libary - may fail if no semaphore or no driver slot is available */
60int rtems_libi2c_initialize ();
61
62/* Bus Driver API
63 *
64 * Bus drivers provide access to low-level i2c functions
65 * such as 'send start', 'send address', 'get bytes' etc.
66 */
67
68/* first field must be a pointer to ops; driver
69 * may add its own fields after this.
70 * the struct that is registered with the library
71 * is not copied; a pointer will we passed
72 * to the callback functions (ops).
73 */
74typedef struct rtems_libi2c_bus_t_
75{
76  struct rtems_libi2c_bus_ops_ *ops;
77  int size;                     /* size of whole structure */
78} rtems_libi2c_bus_t;
79
80/* Access functions a low level driver must provide;
81 *
82 * All of these, except read_bytes and write_bytes
83 * return RTEMS_SUCCESSFUL on success and an error status
84 * otherwise. The read and write ops return the number
85 * of chars read/written or -(status code) on error.
86 */
87typedef struct rtems_libi2c_bus_ops_
88{
89  /* Initialize the bus; might be called again to reset the bus driver */
90  rtems_status_code (*init) (rtems_libi2c_bus_t * bushdl);
91  /* Send start condition */
92  rtems_status_code (*send_start) (rtems_libi2c_bus_t * bushdl);
93  /* Send stop  condition */
94  rtems_status_code (*send_stop) (rtems_libi2c_bus_t * bushdl);
95  /* initiate transfer from (rw!=0) or to a device */
96  rtems_status_code (*send_addr) (rtems_libi2c_bus_t * bushdl,
97                                  uint32_t addr, int rw);
98  /* read a number of bytes */
99  int (*read_bytes) (rtems_libi2c_bus_t * bushdl, unsigned char *bytes,
100                     int nbytes);
101  /* write a number of bytes */
102  int (*write_bytes) (rtems_libi2c_bus_t * bushdl, unsigned char *bytes,
103                      int nbytes);
104} rtems_libi2c_bus_ops_t;
105
106
107/*
108 * Register a lowlevel driver
109 *
110 * TODO: better description
111 *
112 * This  allocates a major number identifying *this* driver
113 * (i.e., libi2c) and the minor number encodes a bus# and a i2c address.
114 *
115 * The name will be registered in the filesystem (parent
116 * directories must exist, also IMFS filesystem must exist see
117 * CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM). It may be NULL in which case
118 * the library will pick a default.
119 *
120 * RETURNS: bus # (>=0) or -1 on error (errno set).
121 */
122
123int rtems_libi2c_register_bus (char *name, rtems_libi2c_bus_t * bus);
124
125extern rtems_device_major_number rtems_libi2c_major;
126
127#define RTEMS_LIBI2C_MAKE_MINOR(busno, i2caddr) \
128        ((((busno)&((1<<3)-1))<<10) | ((i2caddr)&((1<<10)-1)))
129
130/* After the library is initialized, a major number is available.
131 * As soon as a low-level bus driver is registered (above routine
132 * returns a 'busno'), a device node can be created in the filesystem
133 * with a major/minor number pair of
134 *
135 *    rtems_libi2c_major / RTEMS_LIBI2C_MAKE_MINOR(busno, i2caddr)
136 *
137 * and a 'raw' hi-level driver is then attached to this device
138 * node.
139 * This 'raw' driver has very simple semantics:
140 *
141 *   'open'         sends a start condition
142 *   'read'/'write' address the device identified by the i2c bus# and address
143 *                  encoded in the minor number and read or write, respectively
144 *                  a stream of bytes from or to the device. Every time the
145 *                  direction is changed, a 're-start' condition followed by
146 *                  an 'address' cycle is generated on the i2c bus.
147 *   'close'        sends a stop condition.
148 *
149 * Hence, using the 'raw' driver, e.g., 100 bytes at offset 0x200 can be
150 * read from an EEPROM by the following pseudo-code:
151 *
152 *   mknod("/dev/i2c-54", mode, MKDEV(rtems_libi2c_major, RTEMS_LIBI2C_MAKE_MINOR(0,0x54)))
153 *
154 *   int fd;
155 *   char off[2]={0x02,0x00};
156 *
157 *   fd = open("/dev/i2c-54",O_RDWR);
158 *   write(fd,off,2);
159 *   read(fd,buf,100);
160 *   close(fd);
161 *
162 */
163
164/* Higher Level Driver API
165 *
166 * Higher level drivers know how to deal with specific i2c
167 * devices (independent of the bus interface chip) and provide
168 * an abstraction, i.e., the usual read/write/ioctl access.
169 *
170 * Using the above example, such a high level driver could
171 * prevent the user from issuing potentially destructive write
172 * operations (the aforementioned EEPROM interprets any 3rd
173 * and following byte written to the device as data, i.e., the
174 * contents could easily be changed!).
175 * The correct 'read-pointer offset' programming could be
176 * implemented in 'open' and 'ioctl' of a high-level driver and
177 * the user would then only have to perform harmless read
178 * operations, e.g.,
179 *
180 *    fd = open("/dev/i2c.eeprom",O_RDONLY) / * opens and sets EEPROM read pointer * /
181 *    ioctl(fd, IOCTL_SEEK, 0x200)                      / * repositions the read pointer       * /
182 *    read(fd, buf, 100)
183 *    close(fd)
184 *
185 */
186
187/* struct provided at driver registration. The driver may store
188 * private data behind the mandatory first fields but the size
189 * must be set to the size of the entire struct, e.g.,
190 *
191 * struct driver_pvt {
192 *      rtems_libi2c_drv_t pub;
193 *      struct {  ...    } pvt;
194 * } my_driver = {
195 *              {  ops: my_ops,
196 *                size: sizeof(my_driver)
197 *              },
198 *              { ...};
199 * };
200 *
201 * A pointer to this struct is passed to the callback ops.
202 */
203
204typedef struct rtems_libi2c_drv_t_
205{
206  rtems_driver_address_table *ops;      /* the driver ops */
207  int size;                     /* size of whole structure (including appended private data) */
208} rtems_libi2c_drv_t;
209
210/*
211 * The high level driver must be registered with a particular
212 * bus number and i2c address.
213 *
214 * The registration procedure also creates a filesystem node,
215 * i.e., the returned minor number is not really needed.
216 *
217 * If the 'name' argument is NULL, no filesystem node is
218 * created (but this can be done 'manually' using rtems_libi2c_major
219 * and the return value of this routine).
220 *
221 * RETURNS minor number (FYI) or -1 on failure
222 */
223int
224rtems_libi2c_register_drv (char *name, rtems_libi2c_drv_t * drvtbl,
225                           unsigned bus, unsigned i2caddr);
226
227/* Operations available to high level drivers */
228
229/* NOTES: The bus a device is attached to is LOCKED from the first send_start
230 *        until send_stop is executed!
231 *
232 *        Bus tenure MUST NOT span multiple system calls - otherwise, a single
233 *        thread could get into the protected sections (or would deadlock if the
234 *                mutex was not nestable).
235 *                E.g., consider what happens if 'open' sends a 'start' and 'close'
236 *                sends a 'stop' (i.e., the bus mutex would be locked in 'open' and
237 *        released in 'close'. A single thread could try to open two devices
238 *        on the same bus and would either deadlock or nest into the bus mutex
239 *        and potentially mess up the i2c messages.
240 *
241 *        The correct way is to *always* relinquish the i2c bus (i.e., send 'stop'
242 *                from any driver routine prior to returning control to the caller.
243 *                Consult the implementation of the generic driver routines (open, close, ...)
244 *                below or the examples in i2c-2b-eeprom.c and i2c-2b-ds1621.c
245 *
246 * Drivers just pass the minor number on to these routines...
247 */
248rtems_status_code rtems_libi2c_send_start (rtems_device_minor_number minor);
249
250rtems_status_code rtems_libi2c_send_stop (rtems_device_minor_number minor);
251
252rtems_status_code
253rtems_libi2c_send_addr (rtems_device_minor_number minor, int rw);
254
255/* the read/write routines return the number of bytes transferred
256 * or -(status_code) on error.
257 */
258int
259rtems_libi2c_read_bytes (rtems_device_minor_number minor,
260                         unsigned char *bytes, int nbytes);
261
262int
263rtems_libi2c_write_bytes (rtems_device_minor_number minor,
264                          unsigned char *bytes, int nbytes);
265
266/* Send start, send address and read bytes */
267int
268rtems_libi2c_start_read_bytes (uint32_t minor, unsigned char *bytes,
269                               int nbytes);
270
271/* Send start, send address and write bytes */
272int
273rtems_libi2c_start_write_bytes (uint32_t minor, unsigned char *bytes,
274                                int nbytes);
275
276#ifdef __cplusplus
277}
278#endif
279
280#endif
Note: See TracBrowser for help on using the repository browser.