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