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

4.104.114.84.95
Last change on this file since 6128a4a was 6128a4a, checked in by Ralf Corsepius <ralf.corsepius@…>, on 04/21/04 at 10:43:04

Remove stray white spaces.

  • Property mode set to 100644
File size: 8.2 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(uint32_t         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(uint32_t         arg)
42{
43    rtems_boolean *poll_done_flag = (rtems_boolean *)arg;
44    *poll_done_flag = 1;
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, i2c_transfer_sema_done_func, sema);
76    if (sc != RTEMS_SUCCESSFUL)
77    {
78        rtems_semaphore_delete(sema);
79        return sc;
80    }
81    rtems_semaphore_obtain(sema, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
82    sc = rtems_semaphore_delete(sema);
83    return sc;
84}
85
86/* i2c_transfer_wait_poll --
87 *     Initiate I2C bus transfer and wait by poll transaction done flag until
88 *     this transfer will be finished.
89 *
90 * PARAMETERS:
91 *     bus - I2C bus number
92 *     msg - pointer to transfer messages array
93 *     nmsg - number of messages in transfer
94 *
95 * RETURNS:
96 *     RTEMS_SUCCESSFUL
97 */
98static rtems_status_code
99i2c_transfer_wait_poll(i2c_bus_number bus, i2c_message *msg, int nmsg)
100{
101    volatile rtems_boolean poll_done_flag;
102    rtems_status_code sc;
103    poll_done_flag = 0;
104    sc = i2c_transfer(bus, nmsg, msg, i2c_transfer_poll_done_func,
105                      (uint32_t)&poll_done_flag);
106    if (sc != RTEMS_SUCCESSFUL)
107        return sc;
108    while (poll_done_flag == 0)
109    {
110        i2c_poll(bus);
111    }
112    return RTEMS_SUCCESSFUL;
113}
114
115/* i2c_transfer_wait --
116 *     Initiate I2C bus transfer and block until this transfer will be
117 *     finished. This function wait the semaphore if system in
118 *     SYSTEM_STATE_UP state, or poll done flag in other states.
119 *
120 * PARAMETERS:
121 *     bus - I2C bus number
122 *     msg - pointer to transfer messages array
123 *     nmsg - number of messages in transfer
124 *
125 * RETURNS:
126 *     I2C_SUCCESSFUL, if tranfer finished successfully,
127 *     I2C_RESOURCE_NOT_AVAILABLE, if semaphore operations has failed,
128 *     value of status field of first error-finished message in transfer,
129 *     if something wrong.
130 */
131i2c_message_status
132i2c_transfer_wait(i2c_bus_number bus, i2c_message *msg, int nmsg)
133{
134    rtems_status_code sc;
135    int i;
136    if (_System_state_Is_up(_System_state_Get()))
137    {
138        sc = i2c_transfer_wait_sema(bus, msg, nmsg);
139    }
140    else
141    {
142        sc = i2c_transfer_wait_poll(bus, msg, nmsg);
143    }
144
145    if (sc != RTEMS_SUCCESSFUL)
146        return I2C_RESOURCE_NOT_AVAILABLE;
147
148    for (i = 0; i < nmsg; i++)
149    {
150        if (msg[i].status != I2C_SUCCESSFUL)
151        {
152            return msg[i].status;
153        }
154    }
155    return I2C_SUCCESSFUL;
156}
157
158
159/* i2c_write --
160 *     Send single message over specified I2C bus to addressed device and
161 *     wait while transfer is finished.
162 *
163 * PARAMETERS:
164 *     bus  - I2C bus number
165 *     addr - address of I2C device
166 *     buf  - data to be sent to device
167 *     size - data buffer size
168 *
169 * RETURNS:
170 *     transfer status
171 */
172i2c_message_status
173i2c_write(i2c_bus_number bus, i2c_address addr, void *buf, int size)
174{
175    i2c_message msg;
176    msg.addr = addr;
177    msg.flags = I2C_MSG_WR;
178    if (addr > 0xff)
179        msg.flags |= I2C_MSG_ADDR_10;
180    msg.status = 0;
181    msg.len = size;
182    msg.buf = buf;
183    return i2c_transfer_wait(bus, &msg, 1);
184}
185
186/* i2c_wrbyte --
187 *     Send single one-byte long message over specified I2C bus to
188 *     addressed device and wait while transfer is finished.
189 *
190 * PARAMETERS:
191 *     bus  - I2C bus number
192 *     addr - address of I2C device
193 *     cmd  - byte message to be sent to device
194 *
195 * RETURNS:
196 *     transfer status
197 */
198i2c_message_status
199i2c_wrbyte(i2c_bus_number bus, i2c_address addr, uint8_t         cmd)
200{
201    i2c_message msg;
202    uint8_t         data = cmd;
203    msg.addr = addr;
204    msg.flags = I2C_MSG_WR;
205    if (addr > 0xff)
206        msg.flags |= I2C_MSG_ADDR_10;
207    msg.status = 0;
208    msg.len = sizeof(data);
209    msg.buf = &data;
210    return i2c_transfer_wait(bus, &msg, 1);
211}
212
213/* i2c_read --
214 *     receive single message over specified I2C bus from addressed device.
215 *     This call will wait while transfer is finished.
216 *
217 * PARAMETERS:
218 *     bus  - I2C bus number
219 *     addr - address of I2C device
220 *     buf  - buffer for received message
221 *     size - receive buffer size
222 *
223 * RETURNS:
224 *     transfer status
225 */
226i2c_message_status
227i2c_read(i2c_bus_number bus, i2c_address addr, void *buf, int size)
228{
229    i2c_message msg;
230    msg.addr = addr;
231    msg.flags = 0;
232    if (addr > 0xff)
233        msg.flags |= I2C_MSG_ADDR_10;
234    msg.status = 0;
235    msg.len = size;
236    msg.buf = buf;
237    return i2c_transfer_wait(bus, &msg, 1);
238}
239
240/* i2c_wrrd --
241 *     Send message over I2C bus to specified device and receive message
242 *     from the same device during single transfer.
243 *
244 * PARAMETERS:
245 *     bus   - I2C bus number
246 *     addr  - address of I2C device
247 *     bufw  - data to be sent to device
248 *     sizew - send data buffer size
249 *     bufr  - buffer for received message
250 *     sizer - receive buffer size
251 *
252 * RETURNS:
253 *     transfer status
254 */
255i2c_message_status
256i2c_wrrd(i2c_bus_number bus, i2c_address addr, void *bufw, int sizew,
257         void *bufr, int sizer)
258{
259    i2c_message msg[2];
260    msg[0].addr = addr;
261    msg[0].flags = I2C_MSG_WR | I2C_MSG_ERRSKIP;
262    if (addr > 0xff)
263        msg[0].flags |= I2C_MSG_ADDR_10;
264    msg[0].status = 0;
265    msg[0].len = sizew;
266    msg[0].buf = bufw;
267
268    msg[1].addr = addr;
269    msg[1].flags = 0;
270    if (addr > 0xff)
271        msg[1].flags |= I2C_MSG_ADDR_10;
272    msg[1].status = 0;
273    msg[1].len = sizer;
274    msg[1].buf = bufr;
275
276    return i2c_transfer_wait(bus, msg, 2);
277}
278
279/* i2c_wbrd --
280 *     Send one-byte message over I2C bus to specified device and receive
281 *     message from the same device during single transfer.
282 *
283 * PARAMETERS:
284 *     bus   - I2C bus number
285 *     addr  - address of I2C device
286 *     cmd   - one-byte message to be sent over I2C bus
287 *     bufr  - buffer for received message
288 *     sizer - receive buffer size
289 *
290 * RETURNS:
291 *     transfer status
292 */
293i2c_message_status
294i2c_wbrd(i2c_bus_number bus, i2c_address addr, uint8_t         cmd,
295         void *bufr, int sizer)
296{
297    i2c_message msg[2];
298    uint8_t         bufw = cmd;
299    msg[0].addr = addr;
300    msg[0].flags = I2C_MSG_WR | I2C_MSG_ERRSKIP;
301    if (addr > 0xff)
302        msg[0].flags |= I2C_MSG_ADDR_10;
303    msg[0].status = 0;
304    msg[0].len = sizeof(bufw);
305    msg[0].buf = &bufw;
306
307    msg[1].addr = addr;
308    msg[1].flags = I2C_MSG_ERRSKIP;
309    if (addr > 0xff)
310        msg[1].flags |= I2C_MSG_ADDR_10;
311    msg[1].status = 0;
312    msg[1].len = sizer;
313    msg[1].buf = bufr;
314
315    return i2c_transfer_wait(bus, msg, 2);
316}
Note: See TracBrowser for help on using the repository browser.