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