xref: /freebsd/sys/dev/iicbus/iic.c (revision 7937bfbc0ca53fe7cdd0d54414f9296e273a518e)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 1998, 2001 Nicolas Souchu
5  * Copyright (c) 2023 Juniper Networks, Inc.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  */
30 #include <sys/param.h>
31 #include <sys/abi_compat.h>
32 #include <sys/bus.h>
33 #include <sys/conf.h>
34 #include <sys/fcntl.h>
35 #include <sys/lock.h>
36 #include <sys/kernel.h>
37 #include <sys/malloc.h>
38 #include <sys/module.h>
39 #include <sys/sx.h>
40 #include <sys/systm.h>
41 #include <sys/uio.h>
42 #include <sys/errno.h>
43 
44 #include <dev/iicbus/iiconf.h>
45 #include <dev/iicbus/iicbus.h>
46 #include <dev/iicbus/iic.h>
47 
48 #include "iicbus_if.h"
49 
50 struct iic_softc {
51 	device_t sc_dev;
52 	struct cdev *sc_devnode;
53 };
54 
55 struct iic_cdevpriv {
56 	struct sx lock;
57 	struct iic_softc *sc;
58 	bool started;
59 	uint8_t addr;
60 };
61 
62 #ifdef COMPAT_FREEBSD32
63 struct iic_msg32 {
64 	uint16_t slave;
65 	uint16_t flags;
66 	uint16_t len;
67 	uint32_t buf;
68 };
69 
70 struct iiccmd32 {
71 	u_char slave;
72 	uint32_t count;
73 	uint32_t last;
74 	uint32_t buf;
75 };
76 
77 struct iic_rdwr_data32 {
78 	uint32_t msgs;
79 	uint32_t nmsgs;
80 };
81 
82 #define	I2CWRITE32	_IOW('i', 4, struct iiccmd32)
83 #define	I2CREAD32	_IOW('i', 5, struct iiccmd32)
84 #define	I2CRDWR32	_IOW('i', 6, struct iic_rdwr_data32)
85 #endif
86 
87 #define	IIC_LOCK(cdp)			sx_xlock(&(cdp)->lock)
88 #define	IIC_UNLOCK(cdp)			sx_xunlock(&(cdp)->lock)
89 
90 static MALLOC_DEFINE(M_IIC, "iic", "I2C device data");
91 
92 static int iic_probe(device_t);
93 static int iic_attach(device_t);
94 static int iic_detach(device_t);
95 static void iic_identify(driver_t *driver, device_t parent);
96 static void iicdtor(void *data);
97 static int iicuio_move(struct iic_cdevpriv *priv, struct uio *uio, int last);
98 static int iicuio(struct cdev *dev, struct uio *uio, int ioflag);
99 static int iicrdwr(struct iic_cdevpriv *priv, struct iic_rdwr_data *d, int flags, bool compat32);
100 
101 static device_method_t iic_methods[] = {
102 	/* device interface */
103 	DEVMETHOD(device_identify,	iic_identify),
104 	DEVMETHOD(device_probe,		iic_probe),
105 	DEVMETHOD(device_attach,	iic_attach),
106 	DEVMETHOD(device_detach,	iic_detach),
107 
108 	/* iicbus interface */
109 	DEVMETHOD(iicbus_intr,		iicbus_generic_intr),
110 
111 	{ 0, 0 }
112 };
113 
114 static driver_t iic_driver = {
115 	"iic",
116 	iic_methods,
117 	sizeof(struct iic_softc),
118 };
119 
120 static	d_open_t	iicopen;
121 static	d_ioctl_t	iicioctl;
122 
123 static struct cdevsw iic_cdevsw = {
124 	.d_version =	D_VERSION,
125 	.d_open =	iicopen,
126 	.d_read =	iicuio,
127 	.d_write =	iicuio,
128 	.d_ioctl =	iicioctl,
129 	.d_name =	"iic",
130 };
131 
132 static void
133 iic_identify(driver_t *driver, device_t parent)
134 {
135 
136 	if (device_find_child(parent, "iic", -1) == NULL)
137 		BUS_ADD_CHILD(parent, 0, "iic", DEVICE_UNIT_ANY);
138 }
139 
140 static int
141 iic_probe(device_t dev)
142 {
143 	if (iicbus_get_addr(dev) > 0)
144 		return (ENXIO);
145 
146 	device_set_desc(dev, "I2C generic I/O");
147 
148 	return (0);
149 }
150 
151 static int
152 iic_attach(device_t dev)
153 {
154 	struct iic_softc *sc;
155 
156 	sc = device_get_softc(dev);
157 	sc->sc_dev = dev;
158 	sc->sc_devnode = make_dev(&iic_cdevsw, device_get_unit(dev),
159 			UID_ROOT, GID_WHEEL,
160 			0600, "iic%d", device_get_unit(dev));
161 	if (sc->sc_devnode == NULL) {
162 		device_printf(dev, "failed to create character device\n");
163 		return (ENXIO);
164 	}
165 	sc->sc_devnode->si_drv1 = sc;
166 
167 	return (0);
168 }
169 
170 static int
171 iic_detach(device_t dev)
172 {
173 	struct iic_softc *sc;
174 
175 	sc = device_get_softc(dev);
176 
177 	if (sc->sc_devnode)
178 		destroy_dev(sc->sc_devnode);
179 
180 	return (0);
181 }
182 
183 static int
184 iicopen(struct cdev *dev, int flags, int fmt, struct thread *td)
185 {
186 	struct iic_cdevpriv *priv;
187 	int error;
188 
189 	priv = malloc(sizeof(*priv), M_IIC, M_WAITOK | M_ZERO);
190 
191 	sx_init(&priv->lock, "iic");
192 	priv->sc = dev->si_drv1;
193 
194 	error = devfs_set_cdevpriv(priv, iicdtor);
195 	if (error != 0)
196 		free(priv, M_IIC);
197 
198 	return (error);
199 }
200 
201 static void
202 iicdtor(void *data)
203 {
204 	device_t iicdev, parent;
205 	struct iic_cdevpriv *priv;
206 
207 	priv = data;
208 	KASSERT(priv != NULL, ("iic cdevpriv should not be NULL!"));
209 
210 	iicdev = priv->sc->sc_dev;
211 	parent = device_get_parent(iicdev);
212 
213 	if (priv->started) {
214 		iicbus_stop(parent);
215 		iicbus_reset(parent, IIC_UNKNOWN, 0, NULL);
216 		iicbus_release_bus(parent, iicdev);
217 	}
218 
219 	sx_destroy(&priv->lock);
220 	free(priv, M_IIC);
221 }
222 
223 static int
224 iicuio_move(struct iic_cdevpriv *priv, struct uio *uio, int last)
225 {
226 	device_t parent;
227 	int error, num_bytes, transferred_bytes, written_bytes;
228 	char buffer[128];
229 
230 	parent = device_get_parent(priv->sc->sc_dev);
231 	error = 0;
232 
233 	/*
234 	 * We can only transfer up to sizeof(buffer) bytes in 1 shot, so loop until
235 	 * everything has been transferred.
236 	*/
237 	while ((error == 0) && (uio->uio_resid > 0)) {
238 
239 		num_bytes = MIN(uio->uio_resid, sizeof(buffer));
240 		transferred_bytes = 0;
241 
242 		switch (uio->uio_rw) {
243 		case UIO_WRITE:
244 			error = uiomove(buffer, num_bytes, uio);
245 
246 			while ((error == 0) && (transferred_bytes < num_bytes)) {
247 				written_bytes = 0;
248 				error = iicbus_write(parent, &buffer[transferred_bytes],
249 				    num_bytes - transferred_bytes, &written_bytes, 0);
250 				transferred_bytes += written_bytes;
251 			}
252 			break;
253 		case UIO_READ:
254 			error = iicbus_read(parent, buffer,
255 			    num_bytes, &transferred_bytes,
256 			    ((uio->uio_resid <= sizeof(buffer)) ? last : 0), 0);
257 			if (error == 0)
258 				error = uiomove(buffer, transferred_bytes, uio);
259 			break;
260 		}
261 	}
262 
263 	return (error);
264 }
265 
266 static int
267 iicuio(struct cdev *dev, struct uio *uio, int ioflag)
268 {
269 	device_t parent;
270 	struct iic_cdevpriv *priv;
271 	int error;
272 	uint8_t addr;
273 
274 	priv = NULL;
275 	error = devfs_get_cdevpriv((void**)&priv);
276 
277 	if (error != 0)
278 		return (error);
279 	KASSERT(priv != NULL, ("iic cdevpriv should not be NULL!"));
280 
281 	IIC_LOCK(priv);
282 	if (priv->started || (priv->addr == 0)) {
283 		IIC_UNLOCK(priv);
284 		return (ENXIO);
285 	}
286 	parent = device_get_parent(priv->sc->sc_dev);
287 
288 	error = iicbus_request_bus(parent, priv->sc->sc_dev,
289 	    (ioflag & O_NONBLOCK) ? IIC_DONTWAIT : (IIC_WAIT | IIC_INTR));
290 	if (error != 0) {
291 		IIC_UNLOCK(priv);
292 		return (error);
293 	}
294 
295 	switch (uio->uio_rw) {
296 	case UIO_READ:
297 		addr = priv->addr | LSB;
298 		break;
299 	case UIO_WRITE:
300 		addr = priv->addr & ~LSB;
301 		break;
302 	}
303 
304 	error = iicbus_start(parent, addr, 0);
305 	if (error != 0)
306 	{
307 		iicbus_release_bus(parent, priv->sc->sc_dev);
308 		IIC_UNLOCK(priv);
309 		return (error);
310 	}
311 
312 	error = iicuio_move(priv, uio, IIC_LAST_READ);
313 
314 	iicbus_stop(parent);
315 	iicbus_release_bus(parent, priv->sc->sc_dev);
316 	IIC_UNLOCK(priv);
317 	return (error);
318 }
319 
320 #ifdef COMPAT_FREEBSD32
321 static int
322 iic_copyinmsgs32(struct iic_rdwr_data *d, struct iic_msg *buf)
323 {
324 	struct iic_msg32 msg32;
325 	struct iic_msg32 *m32;
326 	int error, i;
327 
328 	m32 = (struct iic_msg32 *)d->msgs;
329 	for (i = 0; i < d->nmsgs; i++) {
330 		error = copyin(&m32[i], &msg32, sizeof(msg32));
331 		if (error != 0)
332 			return (error);
333 		CP(msg32, buf[i], slave);
334 		CP(msg32, buf[i], flags);
335 		CP(msg32, buf[i], len);
336 		PTRIN_CP(msg32, buf[i], buf);
337 	}
338 	return (0);
339 }
340 #endif
341 
342 static int
343 iicrdwr(struct iic_cdevpriv *priv, struct iic_rdwr_data *d, int flags,
344     bool compat32 __unused)
345 {
346 #ifdef COMPAT_FREEBSD32
347 	struct iic_rdwr_data dswab;
348 	struct iic_rdwr_data32 *d32;
349 #endif
350 	struct iic_msg *buf, *m;
351 	void **usrbufs;
352 	device_t iicdev, parent;
353 	int error;
354 	uint32_t i;
355 
356 	iicdev = priv->sc->sc_dev;
357 	parent = device_get_parent(iicdev);
358 	error = 0;
359 #ifdef COMPAT_FREEBSD32
360 	if (compat32) {
361 		d32 = (struct iic_rdwr_data32 *)d;
362 		PTRIN_CP(*d32, dswab, msgs);
363 		CP(*d32, dswab, nmsgs);
364 		d = &dswab;
365 	}
366 #endif
367 
368 	if (d->nmsgs > IIC_RDRW_MAX_MSGS)
369 		return (EINVAL);
370 
371 	buf = malloc(sizeof(*d->msgs) * d->nmsgs, M_IIC, M_WAITOK);
372 
373 #ifdef COMPAT_FREEBSD32
374 	if (compat32)
375 		error = iic_copyinmsgs32(d, buf);
376 	else
377 #endif
378 	error = copyin(d->msgs, buf, sizeof(*d->msgs) * d->nmsgs);
379 	if (error != 0) {
380 		free(buf, M_IIC);
381 		return (error);
382 	}
383 
384 	/* Alloc kernel buffers for userland data, copyin write data */
385 	usrbufs = malloc(sizeof(void *) * d->nmsgs, M_IIC, M_WAITOK | M_ZERO);
386 
387 	for (i = 0; i < d->nmsgs; i++) {
388 		m = &(buf[i]);
389 		usrbufs[i] = m->buf;
390 
391 		/*
392 		 * At least init the buffer to NULL so we can safely free() it later.
393 		 * If the copyin() to buf failed, don't try to malloc bogus m->len.
394 		 */
395 		m->buf = NULL;
396 		if (error != 0)
397 			continue;
398 
399 		/* m->len is uint16_t, so allocation size is capped at 64K. */
400 		m->buf = malloc(m->len, M_IIC, M_WAITOK);
401 		if (!(m->flags & IIC_M_RD))
402 			error = copyin(usrbufs[i], m->buf, m->len);
403 	}
404 
405 	if (error == 0)
406 		error = iicbus_request_bus(parent, iicdev,
407 		    (flags & O_NONBLOCK) ? IIC_DONTWAIT : (IIC_WAIT | IIC_INTR));
408 
409 	if (error == 0) {
410 		error = iicbus_transfer(iicdev, buf, d->nmsgs);
411 		iicbus_release_bus(parent, iicdev);
412 	}
413 
414 	/* Copyout all read segments, free up kernel buffers */
415 	for (i = 0; i < d->nmsgs; i++) {
416 		m = &(buf[i]);
417 		if ((error == 0) && (m->flags & IIC_M_RD))
418 			error = copyout(m->buf, usrbufs[i], m->len);
419 		free(m->buf, M_IIC);
420 	}
421 
422 	free(usrbufs, M_IIC);
423 	free(buf, M_IIC);
424 	return (error);
425 }
426 
427 static int
428 iicioctl(struct cdev *dev, u_long cmd, caddr_t data, int flags, struct thread *td)
429 {
430 #ifdef COMPAT_FREEBSD32
431 	struct iiccmd iicswab;
432 #endif
433 	device_t parent, iicdev;
434 	struct iiccmd *s;
435 #ifdef COMPAT_FREEBSD32
436 	struct iiccmd32 *s32;
437 #endif
438 	struct uio ubuf;
439 	struct iovec uvec;
440 	struct iic_cdevpriv *priv;
441 	int error;
442 	bool compat32;
443 
444 	s = (struct iiccmd *)data;
445 #ifdef COMPAT_FREEBSD32
446 	s32 = (struct iiccmd32 *)data;
447 #endif
448 	error = devfs_get_cdevpriv((void**)&priv);
449 	if (error != 0)
450 		return (error);
451 
452 	KASSERT(priv != NULL, ("iic cdevpriv should not be NULL!"));
453 
454 	iicdev = priv->sc->sc_dev;
455 	parent = device_get_parent(iicdev);
456 	IIC_LOCK(priv);
457 
458 #ifdef COMPAT_FREEBSD32
459 	switch (cmd) {
460 	case I2CWRITE32:
461 	case I2CREAD32:
462 		CP(*s32, iicswab, slave);
463 		CP(*s32, iicswab, count);
464 		CP(*s32, iicswab, last);
465 		PTRIN_CP(*s32, iicswab, buf);
466 		s = &iicswab;
467 		break;
468 	default:
469 		break;
470 	}
471 #endif
472 
473 	switch (cmd) {
474 	case I2CSTART:
475 		if (priv->started) {
476 			error = EINVAL;
477 			break;
478 		}
479 		error = iicbus_request_bus(parent, iicdev,
480 		    (flags & O_NONBLOCK) ? IIC_DONTWAIT : (IIC_WAIT | IIC_INTR));
481 
482 		if (error == 0)
483 			error = iicbus_start(parent, s->slave, 0);
484 
485 		if (error == 0) {
486 			priv->addr = s->slave;
487 			priv->started = true;
488 		} else
489 			iicbus_release_bus(parent, iicdev);
490 
491 		break;
492 
493 	case I2CSTOP:
494 		if (priv->started) {
495 			error = iicbus_stop(parent);
496 			iicbus_release_bus(parent, iicdev);
497 			priv->started = false;
498 		}
499 
500 		break;
501 
502 	case I2CRSTCARD:
503 		/*
504 		 * Bus should be owned before we reset it.
505 		 * We allow the bus to be already owned as the result of an in-progress
506 		 * sequence; however, bus reset will always be followed by release
507 		 * (a new start is presumably needed for I/O anyway). */
508 		if (!priv->started)
509 			error = iicbus_request_bus(parent, iicdev,
510 			    (flags & O_NONBLOCK) ? IIC_DONTWAIT : (IIC_WAIT | IIC_INTR));
511 
512 		if (error == 0) {
513 			error = iicbus_reset(parent, IIC_UNKNOWN, 0, NULL);
514 			/*
515 			 * Ignore IIC_ENOADDR as it only means we have a master-only
516 			 * controller.
517 			 */
518 			if (error == IIC_ENOADDR)
519 				error = 0;
520 
521 			iicbus_release_bus(parent, iicdev);
522 			priv->started = false;
523 		}
524 		break;
525 
526 	case I2CWRITE:
527 #ifdef COMPAT_FREEBSD32
528 	case I2CWRITE32:
529 #endif
530 		if (!priv->started) {
531 			error = EINVAL;
532 			break;
533 		}
534 		uvec.iov_base = s->buf;
535 		uvec.iov_len = s->count;
536 		ubuf.uio_iov = &uvec;
537 		ubuf.uio_iovcnt = 1;
538 		ubuf.uio_segflg = UIO_USERSPACE;
539 		ubuf.uio_td = td;
540 		ubuf.uio_resid = s->count;
541 		ubuf.uio_offset = 0;
542 		ubuf.uio_rw = UIO_WRITE;
543 		error = iicuio_move(priv, &ubuf, 0);
544 		break;
545 
546 	case I2CREAD:
547 #ifdef COMPAT_FREEBSD32
548 	case I2CREAD32:
549 #endif
550 		if (!priv->started) {
551 			error = EINVAL;
552 			break;
553 		}
554 		uvec.iov_base = s->buf;
555 		uvec.iov_len = s->count;
556 		ubuf.uio_iov = &uvec;
557 		ubuf.uio_iovcnt = 1;
558 		ubuf.uio_segflg = UIO_USERSPACE;
559 		ubuf.uio_td = td;
560 		ubuf.uio_resid = s->count;
561 		ubuf.uio_offset = 0;
562 		ubuf.uio_rw = UIO_READ;
563 		error = iicuio_move(priv, &ubuf, s->last);
564 		break;
565 
566 #ifdef COMPAT_FREEBSD32
567 	case I2CRDWR32:
568 #endif
569 	case I2CRDWR:
570 		/*
571 		 * The rdwr list should be a self-contained set of
572 		 * transactions.  Fail if another transaction is in progress.
573                  */
574 		if (priv->started) {
575 			error = EINVAL;
576 			break;
577 		}
578 
579 #ifdef COMPAT_FREEBSD32
580 		compat32 = (cmd == I2CRDWR32);
581 #else
582 		compat32 = false;
583 #endif
584 		error = iicrdwr(priv, (struct iic_rdwr_data *)data, flags,
585 		    compat32);
586 
587 		break;
588 
589 	case I2CRPTSTART:
590 		if (!priv->started) {
591 			error = EINVAL;
592 			break;
593 		}
594 		error = iicbus_repeated_start(parent, s->slave, 0);
595 		break;
596 
597 	case I2CSADDR:
598 		priv->addr = *((uint8_t*)data);
599 		break;
600 
601 	default:
602 		error = ENOTTY;
603 	}
604 
605 	IIC_UNLOCK(priv);
606 	return (error);
607 }
608 
609 DRIVER_MODULE(iic, iicbus, iic_driver, 0, 0);
610 MODULE_DEPEND(iic, iicbus, IICBUS_MINVER, IICBUS_PREFVER, IICBUS_MAXVER);
611 MODULE_VERSION(iic, 1);
612