source: rtems/c/src/lib/libbsp/powerpc/gen5200/i2c/i2c.c @ ca680bc5

4.104.114.84.95
Last change on this file since ca680bc5 was ca680bc5, checked in by Ralf Corsepius <ralf.corsepius@…>, on 12/31/05 at 05:09:26

New (CVS import Thomas Doerfler <Thomas.Doerfler@…>'s
submission).

  • 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 * @(#) i2c.c,v 1.5 2004/04/21 16:01:34 ralf Exp
12 */
13
14#include "../include/bsp.h"
15#include "../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/* i2c_write --
159 *     Send single message over specified I2C bus to addressed device and
160 *     wait while transfer is finished.
161 *
162 * PARAMETERS:
163 *     bus  - I2C bus number
164 *     addr - address of I2C device
165 *     buf  - data to be sent to device
166 *     size - data buffer size
167 *
168 * RETURNS:
169 *     transfer status
170 */
171i2c_message_status
172i2c_write(i2c_bus_number bus, i2c_address addr, void *buf, int size)
173{
174    i2c_message msg;
175    msg.addr = addr;
176    msg.flags = I2C_MSG_WR;
177    if (addr > 0xff)
178        msg.flags |= I2C_MSG_ADDR_10;
179    msg.status = 0;
180    msg.len = size;
181    msg.buf = buf;
182    return i2c_transfer_wait(bus, &msg, 1);
183}
184
185/* i2c_wrbyte --
186 *     Send single one-byte long message over specified I2C bus to
187 *     addressed device and wait while transfer is finished.
188 *
189 * PARAMETERS:
190 *     bus  - I2C bus number
191 *     addr - address of I2C device
192 *     cmd  - byte message to be sent to device
193 *
194 * RETURNS:
195 *     transfer status
196 */
197i2c_message_status
198i2c_wrbyte(i2c_bus_number bus, i2c_address addr, uint8_t         cmd)
199{
200    i2c_message msg;
201    uint8_t         data = cmd;
202    msg.addr = addr;
203    msg.flags = I2C_MSG_WR;
204    if (addr > 0xff)
205        msg.flags |= I2C_MSG_ADDR_10;
206    msg.status = 0;
207    msg.len = sizeof(data);
208    msg.buf = &data;
209    return i2c_transfer_wait(bus, &msg, 1);
210}
211
212/* i2c_read --
213 *     receive single message over specified I2C bus from addressed device.
214 *     This call will wait while transfer is finished.
215 *
216 * PARAMETERS:
217 *     bus  - I2C bus number
218 *     addr - address of I2C device
219 *     buf  - buffer for received message
220 *     size - receive buffer size
221 *
222 * RETURNS:
223 *     transfer status
224 */
225i2c_message_status
226i2c_read(i2c_bus_number bus, i2c_address addr, void *buf, int size)
227{
228    i2c_message msg;
229    msg.addr = addr;
230    msg.flags = 0;
231    if (addr > 0xff)
232        msg.flags |= I2C_MSG_ADDR_10;
233    msg.status = 0;
234    msg.len = size;
235    msg.buf = buf;
236    return i2c_transfer_wait(bus, &msg, 1);
237}
238
239/* i2c_wrrd --
240 *     Send message over I2C bus to specified device and receive message
241 *     from the same device during single transfer.
242 *
243 * PARAMETERS:
244 *     bus   - I2C bus number
245 *     addr  - address of I2C device
246 *     bufw  - data to be sent to device
247 *     sizew - send data buffer size
248 *     bufr  - buffer for received message
249 *     sizer - receive buffer size
250 *
251 * RETURNS:
252 *     transfer status
253 */
254i2c_message_status
255i2c_wrrd(i2c_bus_number bus, i2c_address addr, void *bufw, int sizew,
256         void *bufr, int sizer)
257{
258    i2c_message msg[2];
259    msg[0].addr = addr;
260    msg[0].flags = I2C_MSG_WR | I2C_MSG_ERRSKIP;
261    if (addr > 0xff)
262        msg[0].flags |= I2C_MSG_ADDR_10;
263    msg[0].status = 0;
264    msg[0].len = sizew;
265    msg[0].buf = bufw;
266
267    msg[1].addr = addr;
268    msg[1].flags = 0;
269    if (addr > 0xff)
270        msg[1].flags |= I2C_MSG_ADDR_10;
271    msg[1].status = 0;
272    msg[1].len = sizer;
273    msg[1].buf = bufr;
274
275    return i2c_transfer_wait(bus, msg, 2);
276}
277
278/* i2c_wbrd --
279 *     Send one-byte message over I2C bus to specified device and receive
280 *     message from the same device during single transfer.
281 *
282 * PARAMETERS:
283 *     bus   - I2C bus number
284 *     addr  - address of I2C device
285 *     cmd   - one-byte message to be sent over I2C bus
286 *     bufr  - buffer for received message
287 *     sizer - receive buffer size
288 *
289 * RETURNS:
290 *     transfer status
291 */
292i2c_message_status
293i2c_wbrd(i2c_bus_number bus, i2c_address addr, uint8_t         cmd,
294         void *bufr, int sizer)
295{
296    i2c_message msg[2];
297    uint8_t         bufw = cmd;
298    msg[0].addr = addr;
299    msg[0].flags = I2C_MSG_WR | I2C_MSG_ERRSKIP;
300    if (addr > 0xff)
301        msg[0].flags |= I2C_MSG_ADDR_10;
302    msg[0].status = 0;
303    msg[0].len = sizeof(bufw);
304    msg[0].buf = &bufw;
305
306    msg[1].addr = addr;
307    msg[1].flags = I2C_MSG_ERRSKIP;
308    if (addr > 0xff)
309        msg[1].flags |= I2C_MSG_ADDR_10;
310    msg[1].status = 0;
311    msg[1].len = sizer;
312    msg[1].buf = bufr;
313
314    return i2c_transfer_wait(bus, msg, 2);
315}
Note: See TracBrowser for help on using the repository browser.