1 | # |
---|
2 | # $Id$ |
---|
3 | # |
---|
4 | |
---|
5 | ===================== |
---|
6 | Copyright and License |
---|
7 | ===================== |
---|
8 | |
---|
9 | For Copyright and License of the source code, see the header in |
---|
10 | libi2c.c. |
---|
11 | |
---|
12 | ========= |
---|
13 | Overview |
---|
14 | ======== |
---|
15 | |
---|
16 | This directory contains a general I2C/SPI API library. It offers a |
---|
17 | standard API to I2C or SPI based device drivers, abstracting the low |
---|
18 | level driver (dealing with the I2C/SPI controller hardware of the |
---|
19 | board) from the high-level drivers (dealing with devices connected to |
---|
20 | the I2C or SPI bus). |
---|
21 | |
---|
22 | In most cases throughout this document, i2c and spi devices are |
---|
23 | handled in a similar way. Therefore spi will not be explicitly named |
---|
24 | in every location. |
---|
25 | |
---|
26 | ========= |
---|
27 | Features |
---|
28 | ========= |
---|
29 | |
---|
30 | + supports multiple i2c and/or spi busses |
---|
31 | |
---|
32 | + supports multiple devices connected to each i2c/spi bus |
---|
33 | |
---|
34 | + handles bus and device registration to the I/O manager |
---|
35 | |
---|
36 | ========= |
---|
37 | Structure |
---|
38 | ========= |
---|
39 | |
---|
40 | This library defines a layered API to i2c and spi devices. The |
---|
41 | layering is: |
---|
42 | |
---|
43 | +---------------------------------------+ |
---|
44 | 6| Application | |
---|
45 | +---------------------------------------+ |
---|
46 | 5| RTEMS I/O Manager | |
---|
47 | +---------------------------------------+ |
---|
48 | 4|** libi2c OS adaption layer **| |
---|
49 | +---------------------------------------+ |
---|
50 | 3| high level i2c device driver | |
---|
51 | | (EEPROM, RTC, ...) | |
---|
52 | | (e.g. in c/src/libchip/i2c) | |
---|
53 | +---------------------------------------+ |
---|
54 | 2|** libi2c low level abstration layer **| |
---|
55 | +---------------------------------------+ |
---|
56 | 1| i2c controller driver | |
---|
57 | | (in BSP) | |
---|
58 | +---------------------------------------+ |
---|
59 | |
---|
60 | This document will describe the following interfaces in separate |
---|
61 | sections: |
---|
62 | |
---|
63 | + the interface between the RTEMS I/O Manager and the libi2c OS |
---|
64 | interface (5<->4) |
---|
65 | |
---|
66 | + the interface between the libi2c OS interface and the high level |
---|
67 | i2c device driver (4<->3) |
---|
68 | |
---|
69 | + the interface between the high level i2c device driver and the |
---|
70 | libi2c low level abstraction layer (3<->2) |
---|
71 | |
---|
72 | + the interface between the libi2c low level abstraction layer and |
---|
73 | the i2c controller driver (2<->1) |
---|
74 | |
---|
75 | =================================== |
---|
76 | Differences between i2c and spi bus |
---|
77 | =================================== |
---|
78 | SPI and I2C has many similarities, but also some differences: |
---|
79 | |
---|
80 | - I2C uses inband addressing (the first bits sent select, which slave |
---|
81 | device is addressed) while SPI uses dedicated select lines to address |
---|
82 | a slave device |
---|
83 | |
---|
84 | - SPI supports combined full duplex read-write transactions while I2C |
---|
85 | either sends or receives data from a slave device |
---|
86 | |
---|
87 | - SPI supports a varity of per-slave options, which include: |
---|
88 | - number of bits per character to transfer |
---|
89 | - polarity and phase of clock wrt data |
---|
90 | - clock frequency |
---|
91 | |
---|
92 | The libi2c API defines a superset of functions to handle both flavours |
---|
93 | of serial data transmission, but care should be taken not to use |
---|
94 | features dedicated to the wrong type of serial bus. |
---|
95 | |
---|
96 | |
---|
97 | ====================== |
---|
98 | Library Initialization |
---|
99 | ====================== |
---|
100 | Before any libi2c API is used, the library must be initialized. This |
---|
101 | is achived with a call to function |
---|
102 | |
---|
103 | rtems_libi2c_initialize (). |
---|
104 | |
---|
105 | It creates a global mutex to lock internal data structures and |
---|
106 | registers the OS adaption layer to the RTEMS I/O manager. |
---|
107 | |
---|
108 | Any subsequent call to this function will be silently ignored. |
---|
109 | |
---|
110 | Typically the BSP startup code will perform this initialization. |
---|
111 | |
---|
112 | =================== |
---|
113 | Bus Registration |
---|
114 | =================== |
---|
115 | Each i2c and/or spi bus available must be registerd with a call to |
---|
116 | |
---|
117 | int rtems_libi2c_register_bus (char *name, |
---|
118 | rtems_libi2c_bus_t * bus) |
---|
119 | |
---|
120 | It registers the bus to the libi2c internal data structures and |
---|
121 | creates a device node in the RTEMS filesystem with the given name. If |
---|
122 | no name is given (name==NULL), then the default name "/dev/i2c" is |
---|
123 | used instead. |
---|
124 | |
---|
125 | With the second calling parameter "rtems_libi2c_bus_t * bus" the |
---|
126 | caller passes in a set of function pointers, which define the entries |
---|
127 | into the i2c controller driver (defined in the BSP). |
---|
128 | |
---|
129 | This call returns an integer bus number, which can be used in |
---|
130 | subsequent calls to register devices attached to this bus (see below). |
---|
131 | |
---|
132 | Typically the BSP startup code will perform this registration for each |
---|
133 | bus available on the board. |
---|
134 | |
---|
135 | ========================== |
---|
136 | Device/Driver Registration |
---|
137 | ========================== |
---|
138 | Each device attached to an i2c or spi bus must be registered with a |
---|
139 | call to |
---|
140 | |
---|
141 | int |
---|
142 | rtems_libi2c_register_drv (char *name, rtems_libi2c_drv_t * drvtbl, |
---|
143 | unsigned bus, unsigned i2caddr); |
---|
144 | |
---|
145 | With this call, libi2c is informed, that: |
---|
146 | |
---|
147 | - a device is attached to the given "bus" number (which in fact is the |
---|
148 | return value received from a previous rtems_libi2c_register_bus() |
---|
149 | call) with the address "i2caddr" |
---|
150 | |
---|
151 | - the device is managed by a driver, who's entry functions are listed |
---|
152 | in "drvtbl" |
---|
153 | |
---|
154 | - the device should be registered with the given "name" in the device |
---|
155 | tree of the filesystem. |
---|
156 | |
---|
157 | The call will create a proper minor device number, which has the bus |
---|
158 | number and i2c_address encoded. This minor number is the return value |
---|
159 | of the call and is also associated with the filesystem node created |
---|
160 | for this device. |
---|
161 | |
---|
162 | Note: If you have multiple devices of the same type, you must register |
---|
163 | each of them through a separate call (with the same "drvtbl", but |
---|
164 | different name/bus/i2caddr). |
---|
165 | |
---|
166 | ==================================================================== |
---|
167 | (5<->4) RTEMS I/O Manager and the libi2c OS adaption layer IF |
---|
168 | ==================================================================== |
---|
169 | |
---|
170 | The RTEMS I/O Manager regards the libi2c OS adaption layer as a normal |
---|
171 | RTEMS Device Driver with one unique major number and a set of minor |
---|
172 | numbers, one for each bus and one for each device attached to one of |
---|
173 | the busses. |
---|
174 | |
---|
175 | Therefore the libi2c OS adaption layer provides the standard calls: |
---|
176 | |
---|
177 | static rtems_driver_address_table libi2c_io_ops = { |
---|
178 | initialization_entry: i2c_init, |
---|
179 | open_entry: i2c_open, |
---|
180 | close_entry: i2c_close, |
---|
181 | read_entry: i2c_read, |
---|
182 | write_entry: i2c_write, |
---|
183 | control_entry: i2c_ioctl |
---|
184 | }; |
---|
185 | |
---|
186 | These calls perform some parameter checking and then call the |
---|
187 | appropriate high level i2c device driver function, if available, |
---|
188 | according to the entries in the "drvtbl" passed in the |
---|
189 | rtems_libi2c_register_drv() call. |
---|
190 | |
---|
191 | There are two exceptions: when i2c_read or i2c_write is called with a |
---|
192 | minor number specifying a bus (and not a device attached to the bus), |
---|
193 | then the respective transfer is performed as a raw byte stream |
---|
194 | transfer to the bus. |
---|
195 | |
---|
196 | The main reason for the libi2c OS adaption layer is, that it |
---|
197 | dispatches the RTEMS I/O Manager calls to the proper device driver |
---|
198 | according to the minor number used. |
---|
199 | |
---|
200 | ==================================================================== |
---|
201 | libi2c OS adaption layer and the high level i2c device driver IF |
---|
202 | ==================================================================== |
---|
203 | |
---|
204 | Each high level i2c device driver provides a set of functions in the |
---|
205 | rtems_libi2c_drv_t data structure passed the libi2c when the device is |
---|
206 | registered (see "Device registration" above). These function directly match |
---|
207 | the RTEMS I/O Mangers calls "open", "close", "read", "write", |
---|
208 | "control", and they are passed the same arguments. Functions not |
---|
209 | needed may be ommited (and replaced by a NULL pointer in |
---|
210 | rtems_libi2c_drv_t). |
---|
211 | |
---|
212 | ====================================================================== |
---|
213 | high level i2c device driver and libi2c low level abstraction layer IF |
---|
214 | ====================================================================== |
---|
215 | libi2c provides a set of functions for the high level drivers. These |
---|
216 | functions are: |
---|
217 | |
---|
218 | rtems_libi2c_send_start(); |
---|
219 | rtems_libi2c_send_stop(); |
---|
220 | rtems_libi2c_send_addr(); |
---|
221 | rtems_libi2c_read_bytes(); |
---|
222 | rtems_libi2c_write_bytes(); |
---|
223 | rtems_libi2c_start_read_bytes(); |
---|
224 | rtems_libi2c_start_write_bytes(); |
---|
225 | rtems_libi2c_ioctl(); |
---|
226 | |
---|
227 | Please look into libi2c.h for the proper parameters and return codes. |
---|
228 | |
---|
229 | These functions perform the proper i2c operations when called. |
---|
230 | |
---|
231 | A typical access sequence for the I2C bus would be: |
---|
232 | |
---|
233 | rtems_libi2c_send_start(); |
---|
234 | rtems_libi2c_send_addr(); |
---|
235 | rtems_libi2c_write_bytes(); |
---|
236 | rtems_libi2c_send_stop(); |
---|
237 | |
---|
238 | Alternatively, the rtems_libi2c_write_bytes() call could be relpaced |
---|
239 | with a |
---|
240 | rtems_libi2c_read_bytes() |
---|
241 | |
---|
242 | call or a sequence of multiple calls. |
---|
243 | |
---|
244 | Note: rtems_libi2c_send_start() locks the i2c/spi bus used, so no other |
---|
245 | device can use this i2c/spi bus, until rtems_libi2c_send_stop() function |
---|
246 | is called for the same device. |
---|
247 | |
---|
248 | Special provisions for SPI devices: |
---|
249 | =================================== |
---|
250 | For SPI devices and their drivers, the libi2c interface is used |
---|
251 | slightly differently: |
---|
252 | |
---|
253 | rtems_libi2c_send_start() will lock access to the SPI bus, but has no |
---|
254 | effect on the hardware bus interface. |
---|
255 | |
---|
256 | rtems_libi2c_ioctl(...,RTEMS_LIBI2C_IOCTL_SET_TFRMODE,...) will set |
---|
257 | the transfer mode (bit rate, clock phase and polaritiy, bits per |
---|
258 | char...) according to the rtems_libi2c_tfr_mode_t structure passed in. |
---|
259 | |
---|
260 | rtems_libi2c_send_addr() will activate the proper select line to |
---|
261 | address a certain SPI device. The correspondance between an address |
---|
262 | and the select line pulled is BSP specific. |
---|
263 | |
---|
264 | rtems_libi2c_send_stop(); will deactivate the address line and unlock |
---|
265 | the bus. |
---|
266 | |
---|
267 | A typical access sequence for the SPI bus would be: |
---|
268 | |
---|
269 | rtems_libi2c_send_start(); |
---|
270 | rtems_libi2c_ioctl(...,RTEMS_LIBI2C_IOCTL_SET_TFRMODE,...); |
---|
271 | rtems_libi2c_send_addr(); |
---|
272 | rtems_libi2c_write_bytes(); |
---|
273 | rtems_libi2c_send_stop(); |
---|
274 | |
---|
275 | Alternatively, the rtems_libi2c_write_bytes() call could be relpaced |
---|
276 | with a |
---|
277 | rtems_libi2c_read_bytes() |
---|
278 | or a |
---|
279 | rtems_libi2c_ioctl(...,RTEMS_LIBI2C_IOCTL_READ_WRITE,...) |
---|
280 | call or a sequence of multiple calls. |
---|
281 | |
---|
282 | ==================================================================== |
---|
283 | libi2c low level abstraction layer and i2c controller driver IF |
---|
284 | ==================================================================== |
---|
285 | Each low level i2c/spi driver must provide a set of bus_ops functions |
---|
286 | as defined in the rtems_libi2c_bus_ops_t structure. |
---|
287 | |
---|
288 | typedef struct rtems_libi2c_bus_ops_ |
---|
289 | { |
---|
290 | /* Initialize the bus; might be called again to reset the bus driver */ |
---|
291 | rtems_status_code (*init) (rtems_libi2c_bus_t * bushdl); |
---|
292 | /* Send start condition */ |
---|
293 | rtems_status_code (*send_start) (rtems_libi2c_bus_t * bushdl); |
---|
294 | /* Send stop condition */ |
---|
295 | rtems_status_code (*send_stop) (rtems_libi2c_bus_t * bushdl); |
---|
296 | /* initiate transfer from (rw!=0) or to a device */ |
---|
297 | rtems_status_code (*send_addr) (rtems_libi2c_bus_t * bushdl, |
---|
298 | uint32_t addr, int rw); |
---|
299 | /* read a number of bytes */ |
---|
300 | int (*read_bytes) (rtems_libi2c_bus_t * bushdl, unsigned char *bytes, |
---|
301 | int nbytes); |
---|
302 | /* write a number of bytes */ |
---|
303 | int (*write_bytes) (rtems_libi2c_bus_t * bushdl, unsigned char *bytes, |
---|
304 | int nbytes); |
---|
305 | /* ioctl misc functions */ |
---|
306 | int (*ioctl) (rtems_libi2c_bus_t * bushdl, |
---|
307 | int cmd, |
---|
308 | void *buffer; |
---|
309 | ); |
---|
310 | } rtems_libi2c_bus_ops_t; |
---|
311 | |
---|
312 | Each of these functions performs the corresponding function to the i2c |
---|
313 | bus. |
---|
314 | |
---|
315 | Special provisions for SPI devices: |
---|
316 | =================================== |
---|
317 | For SPI busses, special behaviour is required: |
---|
318 | |
---|
319 | (*send_start) (rtems_libi2c_bus_t * bushdl) |
---|
320 | normally is an empty function. |
---|
321 | |
---|
322 | (*send_addr) (rtems_libi2c_bus_t * bushdl, uint32_t addr, int rw) |
---|
323 | will activate the SPI select line matching to addr. |
---|
324 | |
---|
325 | (*send_stop) (rtems_libi2c_bus_t * bushdl) |
---|
326 | will deactivate the SPI select line |
---|
327 | |
---|
328 | (*ioctl(...,RTEMS_LIBI2C_IOCTL_SET_TFRMODE,...) |
---|
329 | will set the transfer mode (bit rate, clock phase and |
---|
330 | polaritiy, bits per char...) according to the |
---|
331 | rtems_libi2c_tfr_mode_t structure passed in. |
---|
332 | |
---|
333 | (*ioctl(...,RTEMS_LIBI2C_IOCTL_READ_WRITE,...) |
---|
334 | will send and receive data at the same time. |
---|
335 | |
---|
336 | Note: |
---|
337 | |
---|
338 | - low-level I2C drivers normally are specific to the master |
---|
339 | device, but independent from the board hardware. So in many cases they |
---|
340 | can totally reside in libcpu or libchip. |
---|
341 | |
---|
342 | - low-level SPI drivers are mostly board independent, but the |
---|
343 | addressing is board/BSP dependent. Therefore the (*send_start), |
---|
344 | (*send_addr) and (*send_stop) functions are typically defined in the |
---|
345 | BSP. The rest of the functions can reside in libcpu or libchip. |
---|