source: rtems/bsps/powerpc/gen5200/i2c/i2c.c @ a2dad96

5
Last change on this file since a2dad96 was a2dad96, checked in by Sebastian Huber <sebastian.huber@…>, on 04/23/18 at 07:45:28

bsps: Move I2C drivers to bsps

This patch is a part of the BSP source reorganization.

Update #3285.

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