source: rtems/c/src/lib/libbsp/m68k/mcf5206elite/i2c/i2c.c @ d4b4664b

4.104.115
Last change on this file since d4b4664b was d4b4664b, checked in by Ralf Corsepius <ralf.corsepius@…>, on 11/29/09 at 14:59:41

Whitespace removal.

  • Property mode set to 100644
File size: 8.3 KB
Line 
1/* I2C bus common (driver-independent) primitives implementation.
2 *
3 * Copyright (C) 2000 OKTET Ltd., St.-Petersburg, Russia
4 * Author: Victor V. Vengerov <vvv@oktet.ru>
5 *
6 * The license and distribution terms for this file may be
7 * found in the file LICENSE in this distribution or at
8 *
9 * http://www.rtems.com/license/LICENSE.
10 *
11 * @(#) $Id$
12 */
13
14#include <bsp.h>
15#include <i2c.h>
16
17/* i2c_transfer_sema_done_func --
18 *     This function called from I2C driver layer to signal that I2C
19 *     transfer is finished. This function resumes of task execution which
20 *     has invoked blocking I2C primitive.
21 *
22 * PARAMETERS:
23 *     arg - done function argument; it is RTEMS semaphore ID.
24 */
25static void
26i2c_transfer_sema_done_func(void * arg)
27{
28    rtems_id sema = *(rtems_id *)arg;
29    rtems_semaphore_release(sema);
30}
31
32/* i2c_transfer_poll_done_func --
33 *     This function called from I2C driver layer to signal that I2C
34 *     transfer is finished. This function set the flag polled by waiting
35 *     function.
36 *
37 * PARAMETERS:
38 *     arg - done function argument; address of poll_done_flag
39 */
40static void
41i2c_transfer_poll_done_func(void *arg)
42{
43    bool *poll_done_flag = (bool *)arg;
44    *poll_done_flag = true;
45}
46
47/* i2c_transfer_wait_sema --
48 *     Initiate I2C bus transfer and block on temporary created semaphore
49 *     until this transfer will be finished.
50 *
51 * PARAMETERS:
52 *     bus - I2C bus number
53 *     msg - pointer to transfer messages array
54 *     nmsg - number of messages in transfer
55 *
56 * RETURNS:
57 *     RTEMS_SUCCESSFUL, if tranfer finished successfully,
58 *     or RTEMS status code if semaphore operations has failed.
59 */
60static i2c_message_status
61i2c_transfer_wait_sema(i2c_bus_number bus, i2c_message *msg, int nmsg)
62{
63    rtems_status_code sc;
64    rtems_id sema;
65    sc = rtems_semaphore_create(
66        rtems_build_name('I', '2', 'C', 'S'),
67        0,
68        RTEMS_COUNTING_SEMAPHORE | RTEMS_NO_INHERIT_PRIORITY |
69        RTEMS_NO_PRIORITY_CEILING | RTEMS_LOCAL,
70        0,
71        &sema
72    );
73    if (sc != RTEMS_SUCCESSFUL)
74        return I2C_RESOURCE_NOT_AVAILABLE;
75    sc = i2c_transfer(bus, nmsg, msg,
76                      i2c_transfer_sema_done_func, &sema);
77    if (sc != RTEMS_SUCCESSFUL)
78    {
79        rtems_semaphore_delete(sema);
80        return sc;
81    }
82    rtems_semaphore_obtain(sema, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
83    sc = rtems_semaphore_delete(sema);
84    return sc;
85}
86
87/* i2c_transfer_wait_poll --
88 *     Initiate I2C bus transfer and wait by poll transaction done flag until
89 *     this transfer will be finished.
90 *
91 * PARAMETERS:
92 *     bus - I2C bus number
93 *     msg - pointer to transfer messages array
94 *     nmsg - number of messages in transfer
95 *
96 * RETURNS:
97 *     RTEMS_SUCCESSFUL
98 */
99static rtems_status_code
100i2c_transfer_wait_poll(i2c_bus_number bus, i2c_message *msg, int nmsg)
101{
102  /*
103   * this looks nasty, but is correct:
104   * we wait in this function, until the poll_done_flag is
105   * set deep inside the i2c_poll() function
106   */
107    volatile bool poll_done_flag;
108    rtems_status_code sc;
109    poll_done_flag = false;
110    sc = i2c_transfer(bus, nmsg, msg,
111                      i2c_transfer_poll_done_func,(void *)&poll_done_flag);
112    if (sc != RTEMS_SUCCESSFUL)
113        return sc;
114    while (poll_done_flag == false)
115    {
116        i2c_poll(bus);
117    }
118    return RTEMS_SUCCESSFUL;
119}
120
121/* i2c_transfer_wait --
122 *     Initiate I2C bus transfer and block until this transfer will be
123 *     finished. This function wait the semaphore if system in
124 *     SYSTEM_STATE_UP state, or poll done flag in other states.
125 *
126 * PARAMETERS:
127 *     bus - I2C bus number
128 *     msg - pointer to transfer messages array
129 *     nmsg - number of messages in transfer
130 *
131 * RETURNS:
132 *     I2C_SUCCESSFUL, if tranfer finished successfully,
133 *     I2C_RESOURCE_NOT_AVAILABLE, if semaphore operations has failed,
134 *     value of status field of first error-finished message in transfer,
135 *     if something wrong.
136 */
137i2c_message_status
138i2c_transfer_wait(i2c_bus_number bus, i2c_message *msg, int nmsg)
139{
140    rtems_status_code sc;
141    int i;
142    if (_System_state_Is_up(_System_state_Get()))
143    {
144        sc = i2c_transfer_wait_sema(bus, msg, nmsg);
145    }
146    else
147    {
148        sc = i2c_transfer_wait_poll(bus, msg, nmsg);
149    }
150
151    if (sc != RTEMS_SUCCESSFUL)
152        return I2C_RESOURCE_NOT_AVAILABLE;
153
154    for (i = 0; i < nmsg; i++)
155    {
156        if (msg[i].status != I2C_SUCCESSFUL)
157        {
158            return msg[i].status;
159        }
160    }
161    return I2C_SUCCESSFUL;
162}
163
164/* i2c_write --
165 *     Send single message over specified I2C bus to addressed device and
166 *     wait while transfer is finished.
167 *
168 * PARAMETERS:
169 *     bus  - I2C bus number
170 *     addr - address of I2C device
171 *     buf  - data to be sent to device
172 *     size - data buffer size
173 *
174 * RETURNS:
175 *     transfer status
176 */
177i2c_message_status
178i2c_write(i2c_bus_number bus, i2c_address addr, void *buf, int size)
179{
180    i2c_message msg;
181    msg.addr = addr;
182    msg.flags = I2C_MSG_WR;
183    if (addr > 0xff)
184        msg.flags |= I2C_MSG_ADDR_10;
185    msg.status = 0;
186    msg.len = size;
187    msg.buf = buf;
188    return i2c_transfer_wait(bus, &msg, 1);
189}
190
191/* i2c_wrbyte --
192 *     Send single one-byte long message over specified I2C bus to
193 *     addressed device and wait while transfer is finished.
194 *
195 * PARAMETERS:
196 *     bus  - I2C bus number
197 *     addr - address of I2C device
198 *     cmd  - byte message to be sent to device
199 *
200 * RETURNS:
201 *     transfer status
202 */
203i2c_message_status
204i2c_wrbyte(i2c_bus_number bus, i2c_address addr, uint8_t         cmd)
205{
206    i2c_message msg;
207    uint8_t         data = cmd;
208    msg.addr = addr;
209    msg.flags = I2C_MSG_WR;
210    if (addr > 0xff)
211        msg.flags |= I2C_MSG_ADDR_10;
212    msg.status = 0;
213    msg.len = sizeof(data);
214    msg.buf = &data;
215    return i2c_transfer_wait(bus, &msg, 1);
216}
217
218/* i2c_read --
219 *     receive single message over specified I2C bus from addressed device.
220 *     This call will wait while transfer is finished.
221 *
222 * PARAMETERS:
223 *     bus  - I2C bus number
224 *     addr - address of I2C device
225 *     buf  - buffer for received message
226 *     size - receive buffer size
227 *
228 * RETURNS:
229 *     transfer status
230 */
231i2c_message_status
232i2c_read(i2c_bus_number bus, i2c_address addr, void *buf, int size)
233{
234    i2c_message msg;
235    msg.addr = addr;
236    msg.flags = 0;
237    if (addr > 0xff)
238        msg.flags |= I2C_MSG_ADDR_10;
239    msg.status = 0;
240    msg.len = size;
241    msg.buf = buf;
242    return i2c_transfer_wait(bus, &msg, 1);
243}
244
245/* i2c_wrrd --
246 *     Send message over I2C bus to specified device and receive message
247 *     from the same device during single transfer.
248 *
249 * PARAMETERS:
250 *     bus   - I2C bus number
251 *     addr  - address of I2C device
252 *     bufw  - data to be sent to device
253 *     sizew - send data buffer size
254 *     bufr  - buffer for received message
255 *     sizer - receive buffer size
256 *
257 * RETURNS:
258 *     transfer status
259 */
260i2c_message_status
261i2c_wrrd(i2c_bus_number bus, i2c_address addr, void *bufw, int sizew,
262         void *bufr, int sizer)
263{
264    i2c_message msg[2];
265    msg[0].addr = addr;
266    msg[0].flags = I2C_MSG_WR | I2C_MSG_ERRSKIP;
267    if (addr > 0xff)
268        msg[0].flags |= I2C_MSG_ADDR_10;
269    msg[0].status = 0;
270    msg[0].len = sizew;
271    msg[0].buf = bufw;
272
273    msg[1].addr = addr;
274    msg[1].flags = 0;
275    if (addr > 0xff)
276        msg[1].flags |= I2C_MSG_ADDR_10;
277    msg[1].status = 0;
278    msg[1].len = sizer;
279    msg[1].buf = bufr;
280
281    return i2c_transfer_wait(bus, msg, 2);
282}
283
284/* i2c_wbrd --
285 *     Send one-byte message over I2C bus to specified device and receive
286 *     message from the same device during single transfer.
287 *
288 * PARAMETERS:
289 *     bus   - I2C bus number
290 *     addr  - address of I2C device
291 *     cmd   - one-byte message to be sent over I2C bus
292 *     bufr  - buffer for received message
293 *     sizer - receive buffer size
294 *
295 * RETURNS:
296 *     transfer status
297 */
298i2c_message_status
299i2c_wbrd(i2c_bus_number bus, i2c_address addr, uint8_t         cmd,
300         void *bufr, int sizer)
301{
302    i2c_message msg[2];
303    uint8_t         bufw = cmd;
304    msg[0].addr = addr;
305    msg[0].flags = I2C_MSG_WR | I2C_MSG_ERRSKIP;
306    if (addr > 0xff)
307        msg[0].flags |= I2C_MSG_ADDR_10;
308    msg[0].status = 0;
309    msg[0].len = sizeof(bufw);
310    msg[0].buf = &bufw;
311
312    msg[1].addr = addr;
313    msg[1].flags = I2C_MSG_ERRSKIP;
314    if (addr > 0xff)
315        msg[1].flags |= I2C_MSG_ADDR_10;
316    msg[1].status = 0;
317    msg[1].len = sizer;
318    msg[1].buf = bufr;
319
320    return i2c_transfer_wait(bus, msg, 2);
321}
Note: See TracBrowser for help on using the repository browser.