Deleted Added
full compact
iiconf.c (289084) iiconf.c (289095)
1/*-
2 * Copyright (c) 1998 Nicolas Souchu
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 1998 Nicolas Souchu
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: head/sys/dev/iicbus/iiconf.c 289084 2015-10-09 21:34:46Z ian $");
28__FBSDID("$FreeBSD: head/sys/dev/iicbus/iiconf.c 289095 2015-10-09 23:20:08Z ian $");
29
30#include <sys/param.h>
31#include <sys/systm.h>
32#include <sys/lock.h>
33#include <sys/malloc.h>
34#include <sys/module.h>
35#include <sys/mutex.h>
36#include <sys/bus.h>
37
38#include <dev/iicbus/iiconf.h>
39#include <dev/iicbus/iicbus.h>
40#include "iicbus_if.h"
41
42/*
29
30#include <sys/param.h>
31#include <sys/systm.h>
32#include <sys/lock.h>
33#include <sys/malloc.h>
34#include <sys/module.h>
35#include <sys/mutex.h>
36#include <sys/bus.h>
37
38#include <dev/iicbus/iiconf.h>
39#include <dev/iicbus/iicbus.h>
40#include "iicbus_if.h"
41
42/*
43 * Translate IIC_Exxxxx status values to vaguely-equivelent errno values.
44 */
45int
46iic2errno(int iic_status)
47{
48 switch (iic_status) {
49 case IIC_NOERR: return (0);
50 case IIC_EBUSERR: return (EALREADY);
51 case IIC_ENOACK: return (EIO);
52 case IIC_ETIMEOUT: return (ETIMEDOUT);
53 case IIC_EBUSBSY: return (EWOULDBLOCK);
54 case IIC_ESTATUS: return (EPROTO);
55 case IIC_EUNDERFLOW: return (EIO);
56 case IIC_EOVERFLOW: return (EOVERFLOW);
57 case IIC_ENOTSUPP: return (EOPNOTSUPP);
58 case IIC_ENOADDR: return (EADDRNOTAVAIL);
59 case IIC_ERESOURCE: return (ENOMEM);
60 default: return (EIO);
61 }
62}
63
64/*
43 * iicbus_intr()
44 */
45void
46iicbus_intr(device_t bus, int event, char *buf)
47{
48 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus);
49
50 /* call owner's intr routine */
51 if (sc->owner)
52 IICBUS_INTR(sc->owner, event, buf);
53
54 return;
55}
56
57static int
58iicbus_poll(struct iicbus_softc *sc, int how)
59{
60 int error;
61
62 IICBUS_ASSERT_LOCKED(sc);
63 switch (how) {
64 case IIC_WAIT | IIC_INTR:
65 error = mtx_sleep(sc, &sc->lock, IICPRI|PCATCH, "iicreq", 0);
66 break;
67
68 case IIC_WAIT | IIC_NOINTR:
69 error = mtx_sleep(sc, &sc->lock, IICPRI, "iicreq", 0);
70 break;
71
72 default:
73 return (EWOULDBLOCK);
74 }
75
76 return (error);
77}
78
79/*
80 * iicbus_request_bus()
81 *
82 * Allocate the device to perform transfers.
83 *
84 * how : IIC_WAIT or IIC_DONTWAIT
85 */
86int
87iicbus_request_bus(device_t bus, device_t dev, int how)
88{
89 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus);
90 int error = 0;
91
92 IICBUS_LOCK(sc);
93
94 while ((error == 0) && (sc->owner != NULL))
95 error = iicbus_poll(sc, how);
96
97 if (error == 0) {
98 sc->owner = dev;
99 /*
100 * Drop the lock around the call to the bus driver.
101 * This call should be allowed to sleep in the IIC_WAIT case.
102 * Drivers might also need to grab locks that would cause LOR
103 * if our lock is held.
104 */
105 IICBUS_UNLOCK(sc);
106 /* Ask the underlying layers if the request is ok */
107 error = IICBUS_CALLBACK(device_get_parent(bus),
108 IIC_REQUEST_BUS, (caddr_t)&how);
109 IICBUS_LOCK(sc);
110
111 if (error != 0) {
112 sc->owner = NULL;
113 wakeup_one(sc);
114 }
115 }
116
117
118 IICBUS_UNLOCK(sc);
119
120 return (error);
121}
122
123/*
124 * iicbus_release_bus()
125 *
126 * Release the device allocated with iicbus_request_dev()
127 */
128int
129iicbus_release_bus(device_t bus, device_t dev)
130{
131 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus);
132 int error;
133
134 IICBUS_LOCK(sc);
135
136 if (sc->owner != dev) {
137 IICBUS_UNLOCK(sc);
138 return (EACCES);
139 }
140
141 /*
142 * Drop the lock around the call to the bus driver.
143 * This call should be allowed to sleep in the IIC_WAIT case.
144 * Drivers might also need to grab locks that would cause LOR
145 * if our lock is held.
146 */
147 IICBUS_UNLOCK(sc);
148 /* Ask the underlying layers if the release is ok */
149 error = IICBUS_CALLBACK(device_get_parent(bus), IIC_RELEASE_BUS, NULL);
150
151 if (error == 0) {
152 IICBUS_LOCK(sc);
153 sc->owner = NULL;
154
155 /* wakeup a waiting thread */
156 wakeup_one(sc);
157 IICBUS_UNLOCK(sc);
158 }
159
160 return (error);
161}
162
163/*
164 * iicbus_started()
165 *
166 * Test if the iicbus is started by the controller
167 */
168int
169iicbus_started(device_t bus)
170{
171 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus);
172
173 return (sc->started);
174}
175
176/*
177 * iicbus_start()
178 *
179 * Send start condition to the slave addressed by 'slave'
180 */
181int
182iicbus_start(device_t bus, u_char slave, int timeout)
183{
184 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus);
185 int error = 0;
186
187 if (sc->started)
188 return (EINVAL); /* bus already started */
189
190 if (!(error = IICBUS_START(device_get_parent(bus), slave, timeout)))
191 sc->started = slave;
192 else
193 sc->started = 0;
194
195 return (error);
196}
197
198/*
199 * iicbus_repeated_start()
200 *
201 * Send start condition to the slave addressed by 'slave'
202 */
203int
204iicbus_repeated_start(device_t bus, u_char slave, int timeout)
205{
206 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus);
207 int error = 0;
208
209 if (!sc->started)
210 return (EINVAL); /* bus should have been already started */
211
212 if (!(error = IICBUS_REPEATED_START(device_get_parent(bus), slave, timeout)))
213 sc->started = slave;
214 else
215 sc->started = 0;
216
217 return (error);
218}
219
220/*
221 * iicbus_stop()
222 *
223 * Send stop condition to the bus
224 */
225int
226iicbus_stop(device_t bus)
227{
228 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus);
229 int error = 0;
230
231 if (!sc->started)
232 return (EINVAL); /* bus not started */
233
234 error = IICBUS_STOP(device_get_parent(bus));
235
236 /* refuse any further access */
237 sc->started = 0;
238
239 return (error);
240}
241
242/*
243 * iicbus_write()
244 *
245 * Write a block of data to the slave previously started by
246 * iicbus_start() call
247 */
248int
249iicbus_write(device_t bus, const char *buf, int len, int *sent, int timeout)
250{
251 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus);
252
253 /* a slave must have been started for writing */
254 if (sc->started == 0 || (sc->strict != 0 && (sc->started & LSB) != 0))
255 return (EINVAL);
256
257 return (IICBUS_WRITE(device_get_parent(bus), buf, len, sent, timeout));
258}
259
260/*
261 * iicbus_read()
262 *
263 * Read a block of data from the slave previously started by
264 * iicbus_read() call
265 */
266int
267iicbus_read(device_t bus, char *buf, int len, int *read, int last, int delay)
268{
269 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus);
270
271 /* a slave must have been started for reading */
272 if (sc->started == 0 || (sc->strict != 0 && (sc->started & LSB) == 0))
273 return (EINVAL);
274
275 return (IICBUS_READ(device_get_parent(bus), buf, len, read, last, delay));
276}
277
278/*
279 * iicbus_write_byte()
280 *
281 * Write a byte to the slave previously started by iicbus_start() call
282 */
283int
284iicbus_write_byte(device_t bus, char byte, int timeout)
285{
286 char data = byte;
287 int sent;
288
289 return (iicbus_write(bus, &data, 1, &sent, timeout));
290}
291
292/*
293 * iicbus_read_byte()
294 *
295 * Read a byte from the slave previously started by iicbus_start() call
296 */
297int
298iicbus_read_byte(device_t bus, char *byte, int timeout)
299{
300 int read;
301
302 return (iicbus_read(bus, byte, 1, &read, IIC_LAST_READ, timeout));
303}
304
305/*
306 * iicbus_block_write()
307 *
308 * Write a block of data to slave ; start/stop protocol managed
309 */
310int
311iicbus_block_write(device_t bus, u_char slave, char *buf, int len, int *sent)
312{
313 u_char addr = slave & ~LSB;
314 int error;
315
316 if ((error = iicbus_start(bus, addr, 0)))
317 return (error);
318
319 error = iicbus_write(bus, buf, len, sent, 0);
320
321 iicbus_stop(bus);
322
323 return (error);
324}
325
326/*
327 * iicbus_block_read()
328 *
329 * Read a block of data from slave ; start/stop protocol managed
330 */
331int
332iicbus_block_read(device_t bus, u_char slave, char *buf, int len, int *read)
333{
334 u_char addr = slave | LSB;
335 int error;
336
337 if ((error = iicbus_start(bus, addr, 0)))
338 return (error);
339
340 error = iicbus_read(bus, buf, len, read, IIC_LAST_READ, 0);
341
342 iicbus_stop(bus);
343
344 return (error);
345}
346
347/*
348 * iicbus_transfer()
349 *
350 * Do an aribtrary number of transfers on the iicbus. We pass these
351 * raw requests to the bridge driver. If the bridge driver supports
352 * them directly, then it manages all the details. If not, it can use
353 * the helper function iicbus_transfer_gen() which will do the
354 * transfers at a low level.
355 *
356 * Pointers passed in as part of iic_msg must be kernel pointers.
357 * Callers that have user addresses to manage must do so on their own.
358 */
359int
360iicbus_transfer(device_t bus, struct iic_msg *msgs, uint32_t nmsgs)
361{
362 return (IICBUS_TRANSFER(device_get_parent(bus), msgs, nmsgs));
363}
364
365/*
366 * Generic version of iicbus_transfer that calls the appropriate
367 * routines to accomplish this. See note above about acceptable
368 * buffer addresses.
369 */
370int
371iicbus_transfer_gen(device_t dev, struct iic_msg *msgs, uint32_t nmsgs)
372{
373 int i, error, lenread, lenwrote, nkid, rpstart, addr;
374 device_t *children, bus;
375 bool nostop;
376
377 if ((error = device_get_children(dev, &children, &nkid)) != 0)
378 return (error);
379 if (nkid != 1) {
380 free(children, M_TEMP);
381 return (EIO);
382 }
383 bus = children[0];
384 rpstart = 0;
385 free(children, M_TEMP);
386 nostop = iicbus_get_nostop(dev);
387 for (i = 0, error = 0; i < nmsgs && error == 0; i++) {
388 addr = msgs[i].slave;
389 if (msgs[i].flags & IIC_M_RD)
390 addr |= LSB;
391 else
392 addr &= ~LSB;
393
394 if (!(msgs[i].flags & IIC_M_NOSTART)) {
395 if (rpstart)
396 error = iicbus_repeated_start(bus, addr, 0);
397 else
398 error = iicbus_start(bus, addr, 0);
399 }
400 if (error != 0)
401 break;
402
403 if (msgs[i].flags & IIC_M_RD)
404 error = iicbus_read(bus, msgs[i].buf, msgs[i].len,
405 &lenread, IIC_LAST_READ, 0);
406 else
407 error = iicbus_write(bus, msgs[i].buf, msgs[i].len,
408 &lenwrote, 0);
409 if (error != 0)
410 break;
411
412 if ((msgs[i].flags & IIC_M_NOSTOP) != 0 ||
413 (nostop && i + 1 < nmsgs)) {
414 rpstart = 1; /* Next message gets repeated start */
415 } else {
416 rpstart = 0;
417 iicbus_stop(bus);
418 }
419 }
420 if (error != 0 && !nostop)
421 iicbus_stop(bus);
422 return (error);
423}
65 * iicbus_intr()
66 */
67void
68iicbus_intr(device_t bus, int event, char *buf)
69{
70 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus);
71
72 /* call owner's intr routine */
73 if (sc->owner)
74 IICBUS_INTR(sc->owner, event, buf);
75
76 return;
77}
78
79static int
80iicbus_poll(struct iicbus_softc *sc, int how)
81{
82 int error;
83
84 IICBUS_ASSERT_LOCKED(sc);
85 switch (how) {
86 case IIC_WAIT | IIC_INTR:
87 error = mtx_sleep(sc, &sc->lock, IICPRI|PCATCH, "iicreq", 0);
88 break;
89
90 case IIC_WAIT | IIC_NOINTR:
91 error = mtx_sleep(sc, &sc->lock, IICPRI, "iicreq", 0);
92 break;
93
94 default:
95 return (EWOULDBLOCK);
96 }
97
98 return (error);
99}
100
101/*
102 * iicbus_request_bus()
103 *
104 * Allocate the device to perform transfers.
105 *
106 * how : IIC_WAIT or IIC_DONTWAIT
107 */
108int
109iicbus_request_bus(device_t bus, device_t dev, int how)
110{
111 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus);
112 int error = 0;
113
114 IICBUS_LOCK(sc);
115
116 while ((error == 0) && (sc->owner != NULL))
117 error = iicbus_poll(sc, how);
118
119 if (error == 0) {
120 sc->owner = dev;
121 /*
122 * Drop the lock around the call to the bus driver.
123 * This call should be allowed to sleep in the IIC_WAIT case.
124 * Drivers might also need to grab locks that would cause LOR
125 * if our lock is held.
126 */
127 IICBUS_UNLOCK(sc);
128 /* Ask the underlying layers if the request is ok */
129 error = IICBUS_CALLBACK(device_get_parent(bus),
130 IIC_REQUEST_BUS, (caddr_t)&how);
131 IICBUS_LOCK(sc);
132
133 if (error != 0) {
134 sc->owner = NULL;
135 wakeup_one(sc);
136 }
137 }
138
139
140 IICBUS_UNLOCK(sc);
141
142 return (error);
143}
144
145/*
146 * iicbus_release_bus()
147 *
148 * Release the device allocated with iicbus_request_dev()
149 */
150int
151iicbus_release_bus(device_t bus, device_t dev)
152{
153 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus);
154 int error;
155
156 IICBUS_LOCK(sc);
157
158 if (sc->owner != dev) {
159 IICBUS_UNLOCK(sc);
160 return (EACCES);
161 }
162
163 /*
164 * Drop the lock around the call to the bus driver.
165 * This call should be allowed to sleep in the IIC_WAIT case.
166 * Drivers might also need to grab locks that would cause LOR
167 * if our lock is held.
168 */
169 IICBUS_UNLOCK(sc);
170 /* Ask the underlying layers if the release is ok */
171 error = IICBUS_CALLBACK(device_get_parent(bus), IIC_RELEASE_BUS, NULL);
172
173 if (error == 0) {
174 IICBUS_LOCK(sc);
175 sc->owner = NULL;
176
177 /* wakeup a waiting thread */
178 wakeup_one(sc);
179 IICBUS_UNLOCK(sc);
180 }
181
182 return (error);
183}
184
185/*
186 * iicbus_started()
187 *
188 * Test if the iicbus is started by the controller
189 */
190int
191iicbus_started(device_t bus)
192{
193 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus);
194
195 return (sc->started);
196}
197
198/*
199 * iicbus_start()
200 *
201 * Send start condition to the slave addressed by 'slave'
202 */
203int
204iicbus_start(device_t bus, u_char slave, int timeout)
205{
206 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus);
207 int error = 0;
208
209 if (sc->started)
210 return (EINVAL); /* bus already started */
211
212 if (!(error = IICBUS_START(device_get_parent(bus), slave, timeout)))
213 sc->started = slave;
214 else
215 sc->started = 0;
216
217 return (error);
218}
219
220/*
221 * iicbus_repeated_start()
222 *
223 * Send start condition to the slave addressed by 'slave'
224 */
225int
226iicbus_repeated_start(device_t bus, u_char slave, int timeout)
227{
228 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus);
229 int error = 0;
230
231 if (!sc->started)
232 return (EINVAL); /* bus should have been already started */
233
234 if (!(error = IICBUS_REPEATED_START(device_get_parent(bus), slave, timeout)))
235 sc->started = slave;
236 else
237 sc->started = 0;
238
239 return (error);
240}
241
242/*
243 * iicbus_stop()
244 *
245 * Send stop condition to the bus
246 */
247int
248iicbus_stop(device_t bus)
249{
250 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus);
251 int error = 0;
252
253 if (!sc->started)
254 return (EINVAL); /* bus not started */
255
256 error = IICBUS_STOP(device_get_parent(bus));
257
258 /* refuse any further access */
259 sc->started = 0;
260
261 return (error);
262}
263
264/*
265 * iicbus_write()
266 *
267 * Write a block of data to the slave previously started by
268 * iicbus_start() call
269 */
270int
271iicbus_write(device_t bus, const char *buf, int len, int *sent, int timeout)
272{
273 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus);
274
275 /* a slave must have been started for writing */
276 if (sc->started == 0 || (sc->strict != 0 && (sc->started & LSB) != 0))
277 return (EINVAL);
278
279 return (IICBUS_WRITE(device_get_parent(bus), buf, len, sent, timeout));
280}
281
282/*
283 * iicbus_read()
284 *
285 * Read a block of data from the slave previously started by
286 * iicbus_read() call
287 */
288int
289iicbus_read(device_t bus, char *buf, int len, int *read, int last, int delay)
290{
291 struct iicbus_softc *sc = (struct iicbus_softc *)device_get_softc(bus);
292
293 /* a slave must have been started for reading */
294 if (sc->started == 0 || (sc->strict != 0 && (sc->started & LSB) == 0))
295 return (EINVAL);
296
297 return (IICBUS_READ(device_get_parent(bus), buf, len, read, last, delay));
298}
299
300/*
301 * iicbus_write_byte()
302 *
303 * Write a byte to the slave previously started by iicbus_start() call
304 */
305int
306iicbus_write_byte(device_t bus, char byte, int timeout)
307{
308 char data = byte;
309 int sent;
310
311 return (iicbus_write(bus, &data, 1, &sent, timeout));
312}
313
314/*
315 * iicbus_read_byte()
316 *
317 * Read a byte from the slave previously started by iicbus_start() call
318 */
319int
320iicbus_read_byte(device_t bus, char *byte, int timeout)
321{
322 int read;
323
324 return (iicbus_read(bus, byte, 1, &read, IIC_LAST_READ, timeout));
325}
326
327/*
328 * iicbus_block_write()
329 *
330 * Write a block of data to slave ; start/stop protocol managed
331 */
332int
333iicbus_block_write(device_t bus, u_char slave, char *buf, int len, int *sent)
334{
335 u_char addr = slave & ~LSB;
336 int error;
337
338 if ((error = iicbus_start(bus, addr, 0)))
339 return (error);
340
341 error = iicbus_write(bus, buf, len, sent, 0);
342
343 iicbus_stop(bus);
344
345 return (error);
346}
347
348/*
349 * iicbus_block_read()
350 *
351 * Read a block of data from slave ; start/stop protocol managed
352 */
353int
354iicbus_block_read(device_t bus, u_char slave, char *buf, int len, int *read)
355{
356 u_char addr = slave | LSB;
357 int error;
358
359 if ((error = iicbus_start(bus, addr, 0)))
360 return (error);
361
362 error = iicbus_read(bus, buf, len, read, IIC_LAST_READ, 0);
363
364 iicbus_stop(bus);
365
366 return (error);
367}
368
369/*
370 * iicbus_transfer()
371 *
372 * Do an aribtrary number of transfers on the iicbus. We pass these
373 * raw requests to the bridge driver. If the bridge driver supports
374 * them directly, then it manages all the details. If not, it can use
375 * the helper function iicbus_transfer_gen() which will do the
376 * transfers at a low level.
377 *
378 * Pointers passed in as part of iic_msg must be kernel pointers.
379 * Callers that have user addresses to manage must do so on their own.
380 */
381int
382iicbus_transfer(device_t bus, struct iic_msg *msgs, uint32_t nmsgs)
383{
384 return (IICBUS_TRANSFER(device_get_parent(bus), msgs, nmsgs));
385}
386
387/*
388 * Generic version of iicbus_transfer that calls the appropriate
389 * routines to accomplish this. See note above about acceptable
390 * buffer addresses.
391 */
392int
393iicbus_transfer_gen(device_t dev, struct iic_msg *msgs, uint32_t nmsgs)
394{
395 int i, error, lenread, lenwrote, nkid, rpstart, addr;
396 device_t *children, bus;
397 bool nostop;
398
399 if ((error = device_get_children(dev, &children, &nkid)) != 0)
400 return (error);
401 if (nkid != 1) {
402 free(children, M_TEMP);
403 return (EIO);
404 }
405 bus = children[0];
406 rpstart = 0;
407 free(children, M_TEMP);
408 nostop = iicbus_get_nostop(dev);
409 for (i = 0, error = 0; i < nmsgs && error == 0; i++) {
410 addr = msgs[i].slave;
411 if (msgs[i].flags & IIC_M_RD)
412 addr |= LSB;
413 else
414 addr &= ~LSB;
415
416 if (!(msgs[i].flags & IIC_M_NOSTART)) {
417 if (rpstart)
418 error = iicbus_repeated_start(bus, addr, 0);
419 else
420 error = iicbus_start(bus, addr, 0);
421 }
422 if (error != 0)
423 break;
424
425 if (msgs[i].flags & IIC_M_RD)
426 error = iicbus_read(bus, msgs[i].buf, msgs[i].len,
427 &lenread, IIC_LAST_READ, 0);
428 else
429 error = iicbus_write(bus, msgs[i].buf, msgs[i].len,
430 &lenwrote, 0);
431 if (error != 0)
432 break;
433
434 if ((msgs[i].flags & IIC_M_NOSTOP) != 0 ||
435 (nostop && i + 1 < nmsgs)) {
436 rpstart = 1; /* Next message gets repeated start */
437 } else {
438 rpstart = 0;
439 iicbus_stop(bus);
440 }
441 }
442 if (error != 0 && !nostop)
443 iicbus_stop(bus);
444 return (error);
445}