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