]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/iicbus/iic.c
bhyvectl(8): Normalize the man page date
[FreeBSD/FreeBSD.git] / sys / dev / iicbus / iic.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 1998, 2001 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  * $FreeBSD$
29  *
30  */
31 #include <sys/param.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
63 #define IIC_LOCK(cdp)                   sx_xlock(&(cdp)->lock)
64 #define IIC_UNLOCK(cdp)                 sx_xunlock(&(cdp)->lock)
65
66 static MALLOC_DEFINE(M_IIC, "iic", "I2C device data");
67
68 static int iic_probe(device_t);
69 static int iic_attach(device_t);
70 static int iic_detach(device_t);
71 static void iic_identify(driver_t *driver, device_t parent);
72 static void iicdtor(void *data);
73 static int iicuio_move(struct iic_cdevpriv *priv, struct uio *uio, int last);
74 static int iicuio(struct cdev *dev, struct uio *uio, int ioflag);
75 static int iicrdwr(struct iic_cdevpriv *priv, struct iic_rdwr_data *d, int flags);
76
77 static devclass_t iic_devclass;
78
79 static device_method_t iic_methods[] = {
80         /* device interface */
81         DEVMETHOD(device_identify,      iic_identify),
82         DEVMETHOD(device_probe,         iic_probe),
83         DEVMETHOD(device_attach,        iic_attach),
84         DEVMETHOD(device_detach,        iic_detach),
85
86         /* iicbus interface */
87         DEVMETHOD(iicbus_intr,          iicbus_generic_intr),
88
89         { 0, 0 }
90 };
91
92 static driver_t iic_driver = {
93         "iic",
94         iic_methods,
95         sizeof(struct iic_softc),
96 };
97
98 static  d_open_t        iicopen;
99 static  d_ioctl_t       iicioctl;
100
101 static struct cdevsw iic_cdevsw = {
102         .d_version =    D_VERSION,
103         .d_open =       iicopen,
104         .d_read =       iicuio,
105         .d_write =      iicuio,
106         .d_ioctl =      iicioctl,
107         .d_name =       "iic",
108 };
109
110 static void
111 iic_identify(driver_t *driver, device_t parent)
112 {
113
114         if (device_find_child(parent, "iic", -1) == NULL)
115                 BUS_ADD_CHILD(parent, 0, "iic", -1);
116 }
117
118 static int
119 iic_probe(device_t dev)
120 {
121         if (iicbus_get_addr(dev) > 0)
122                 return (ENXIO);
123
124         device_set_desc(dev, "I2C generic I/O");
125
126         return (0);
127 }
128         
129 static int
130 iic_attach(device_t dev)
131 {
132         struct iic_softc *sc;
133
134         sc = device_get_softc(dev);
135         sc->sc_dev = dev;
136         sc->sc_devnode = make_dev(&iic_cdevsw, device_get_unit(dev),
137                         UID_ROOT, GID_WHEEL,
138                         0600, "iic%d", device_get_unit(dev));
139         if (sc->sc_devnode == NULL) {
140                 device_printf(dev, "failed to create character device\n");
141                 return (ENXIO);
142         }
143         sc->sc_devnode->si_drv1 = sc;
144
145         return (0);
146 }
147
148 static int
149 iic_detach(device_t dev)
150 {
151         struct iic_softc *sc;
152
153         sc = device_get_softc(dev);
154
155         if (sc->sc_devnode)
156                 destroy_dev(sc->sc_devnode);
157
158         return (0);
159 }
160
161 static int
162 iicopen(struct cdev *dev, int flags, int fmt, struct thread *td)
163 {
164         struct iic_cdevpriv *priv;
165         int error;
166
167         priv = malloc(sizeof(*priv), M_IIC, M_WAITOK | M_ZERO);
168
169         sx_init(&priv->lock, "iic");
170         priv->sc = dev->si_drv1;
171
172         error = devfs_set_cdevpriv(priv, iicdtor); 
173         if (error != 0)
174                 free(priv, M_IIC);
175
176         return (error);
177 }
178
179 static void
180 iicdtor(void *data)
181 {
182         device_t iicdev, parent;
183         struct iic_cdevpriv *priv;
184
185         priv = data;
186         KASSERT(priv != NULL, ("iic cdevpriv should not be NULL!"));
187
188         iicdev = priv->sc->sc_dev;
189         parent = device_get_parent(iicdev);
190
191         if (priv->started) {
192                 iicbus_stop(parent);
193                 iicbus_reset(parent, IIC_UNKNOWN, 0, NULL);
194                 iicbus_release_bus(parent, iicdev);
195         }
196
197         sx_destroy(&priv->lock);
198         free(priv, M_IIC);
199 }
200
201 static int
202 iicuio_move(struct iic_cdevpriv *priv, struct uio *uio, int last)
203 {
204         device_t parent;
205         int error, num_bytes, transferred_bytes, written_bytes;
206         char buffer[128];
207
208         parent = device_get_parent(priv->sc->sc_dev);
209         error = 0;
210
211         /*
212          * We can only transfer up to sizeof(buffer) bytes in 1 shot, so loop until
213          * everything has been transferred.
214         */
215         while ((error == 0) && (uio->uio_resid > 0)) {
216
217                 num_bytes = MIN(uio->uio_resid, sizeof(buffer));
218                 transferred_bytes = 0;
219
220                 if (uio->uio_rw == UIO_WRITE) {
221                         error = uiomove(buffer, num_bytes, uio);
222
223                         while ((error == 0) && (transferred_bytes < num_bytes)) {
224                                 written_bytes = 0;
225                                 error = iicbus_write(parent, &buffer[transferred_bytes],
226                                     num_bytes - transferred_bytes, &written_bytes, 0);
227                                 transferred_bytes += written_bytes;
228                         }
229                                 
230                 } else if (uio->uio_rw == UIO_READ) {
231                         error = iicbus_read(parent, buffer,
232                             num_bytes, &transferred_bytes,
233                             ((uio->uio_resid <= sizeof(buffer)) ? last : 0), 0);
234                         if (error == 0)
235                                 error = uiomove(buffer, transferred_bytes, uio);
236                 }
237         }
238
239         return (error);
240 }
241
242 static int
243 iicuio(struct cdev *dev, struct uio *uio, int ioflag)
244 {
245         device_t parent;
246         struct iic_cdevpriv *priv;
247         int error;
248         uint8_t addr;
249
250         priv = NULL;
251         error = devfs_get_cdevpriv((void**)&priv);
252
253         if (error != 0)
254                 return (error);
255         KASSERT(priv != NULL, ("iic cdevpriv should not be NULL!"));
256
257         IIC_LOCK(priv);
258         if (priv->started || (priv->addr == 0)) {
259                 IIC_UNLOCK(priv);
260                 return (ENXIO);
261         }
262         parent = device_get_parent(priv->sc->sc_dev);
263
264         error = iicbus_request_bus(parent, priv->sc->sc_dev,
265             (ioflag & O_NONBLOCK) ? IIC_DONTWAIT : (IIC_WAIT | IIC_INTR));
266         if (error != 0) {
267                 IIC_UNLOCK(priv);
268                 return (error);
269         }
270
271         if (uio->uio_rw == UIO_READ)
272                 addr = priv->addr | LSB;
273         else
274                 addr = priv->addr & ~LSB;
275
276         error = iicbus_start(parent, addr, 0);
277         if (error != 0)
278         {
279                 iicbus_release_bus(parent, priv->sc->sc_dev);
280                 IIC_UNLOCK(priv);
281                 return (error);
282         }
283
284         error = iicuio_move(priv, uio, IIC_LAST_READ);
285
286         iicbus_stop(parent);
287         iicbus_release_bus(parent, priv->sc->sc_dev);
288         IIC_UNLOCK(priv);
289         return (error);
290 }
291
292 static int
293 iicrdwr(struct iic_cdevpriv *priv, struct iic_rdwr_data *d, int flags)
294 {
295         struct iic_msg *buf, *m;
296         void **usrbufs;
297         device_t iicdev, parent;
298         int error;
299         uint32_t i;
300
301         iicdev = priv->sc->sc_dev;
302         parent = device_get_parent(iicdev);
303         error = 0;
304
305         if (d->nmsgs > IIC_RDRW_MAX_MSGS)
306                 return (EINVAL);
307
308         buf = malloc(sizeof(*d->msgs) * d->nmsgs, M_IIC, M_WAITOK);
309
310         error = copyin(d->msgs, buf, sizeof(*d->msgs) * d->nmsgs);
311         if (error != 0) {
312                 free(buf, M_IIC);
313                 return (error);
314         }
315
316         /* Alloc kernel buffers for userland data, copyin write data */
317         usrbufs = malloc(sizeof(void *) * d->nmsgs, M_IIC, M_WAITOK | M_ZERO);
318
319         for (i = 0; i < d->nmsgs; i++) {
320                 m = &(buf[i]);
321                 usrbufs[i] = m->buf;
322
323                 /*
324                  * At least init the buffer to NULL so we can safely free() it later.
325                  * If the copyin() to buf failed, don't try to malloc bogus m->len.
326                  */
327                 m->buf = NULL;
328                 if (error != 0)
329                         continue;
330
331                 /* m->len is uint16_t, so allocation size is capped at 64K. */
332                 m->buf = malloc(m->len, M_IIC, M_WAITOK);
333                 if (!(m->flags & IIC_M_RD))
334                         error = copyin(usrbufs[i], m->buf, m->len);
335         }
336
337         if (error == 0)
338                 error = iicbus_request_bus(parent, iicdev,
339                     (flags & O_NONBLOCK) ? IIC_DONTWAIT : (IIC_WAIT | IIC_INTR));
340
341         if (error == 0) {
342                 error = iicbus_transfer(iicdev, buf, d->nmsgs);
343                 iicbus_release_bus(parent, iicdev);
344         }
345
346         /* Copyout all read segments, free up kernel buffers */
347         for (i = 0; i < d->nmsgs; i++) {
348                 m = &(buf[i]);
349                 if ((error == 0) && (m->flags & IIC_M_RD))
350                         error = copyout(m->buf, usrbufs[i], m->len);
351                 free(m->buf, M_IIC);
352         }
353
354         free(usrbufs, M_IIC);
355         free(buf, M_IIC);
356         return (error);
357 }
358
359 static int
360 iicioctl(struct cdev *dev, u_long cmd, caddr_t data, int flags, struct thread *td)
361 {
362         device_t parent, iicdev;
363         struct iiccmd *s;
364         struct uio ubuf;
365         struct iovec uvec;
366         struct iic_cdevpriv *priv;
367         int error;
368
369         s = (struct iiccmd *)data;
370         error = devfs_get_cdevpriv((void**)&priv);
371         if (error != 0)
372                 return (error);
373
374         KASSERT(priv != NULL, ("iic cdevpriv should not be NULL!"));
375
376         iicdev = priv->sc->sc_dev;
377         parent = device_get_parent(iicdev);
378         IIC_LOCK(priv);
379
380
381         switch (cmd) {
382         case I2CSTART:
383                 if (priv->started) {
384                         error = EINVAL;
385                         break;
386                 }
387                 error = iicbus_request_bus(parent, iicdev,
388                     (flags & O_NONBLOCK) ? IIC_DONTWAIT : (IIC_WAIT | IIC_INTR));
389
390                 if (error == 0)
391                         error = iicbus_start(parent, s->slave, 0);
392
393                 if (error == 0) {
394                         priv->addr = s->slave;
395                         priv->started = true;
396                 } else
397                         iicbus_release_bus(parent, iicdev);
398
399                 break;
400
401         case I2CSTOP:
402                 if (priv->started) {
403                         error = iicbus_stop(parent);
404                         iicbus_release_bus(parent, iicdev);
405                         priv->started = false;
406                 }
407
408                 break;
409
410         case I2CRSTCARD:
411                 /*
412                  * Bus should be owned before we reset it.
413                  * We allow the bus to be already owned as the result of an in-progress
414                  * sequence; however, bus reset will always be followed by release
415                  * (a new start is presumably needed for I/O anyway). */ 
416                 if (!priv->started)     
417                         error = iicbus_request_bus(parent, iicdev,
418                             (flags & O_NONBLOCK) ? IIC_DONTWAIT : (IIC_WAIT | IIC_INTR));
419
420                 if (error == 0) {
421                         error = iicbus_reset(parent, IIC_UNKNOWN, 0, NULL);
422                         /*
423                          * Ignore IIC_ENOADDR as it only means we have a master-only
424                          * controller.
425                          */
426                         if (error == IIC_ENOADDR)
427                                 error = 0;
428
429                         iicbus_release_bus(parent, iicdev);
430                         priv->started = false;
431                 }
432                 break;
433
434         case I2CWRITE:
435                 if (!priv->started) {
436                         error = EINVAL;
437                         break;
438                 }
439                 uvec.iov_base = s->buf;
440                 uvec.iov_len = s->count;
441                 ubuf.uio_iov = &uvec;
442                 ubuf.uio_iovcnt = 1;
443                 ubuf.uio_segflg = UIO_USERSPACE;
444                 ubuf.uio_td = td;
445                 ubuf.uio_resid = s->count;
446                 ubuf.uio_offset = 0;
447                 ubuf.uio_rw = UIO_WRITE;
448                 error = iicuio_move(priv, &ubuf, 0);
449                 break;
450
451         case I2CREAD:
452                 if (!priv->started) {
453                         error = EINVAL;
454                         break;
455                 }
456                 uvec.iov_base = s->buf;
457                 uvec.iov_len = s->count;
458                 ubuf.uio_iov = &uvec;
459                 ubuf.uio_iovcnt = 1;
460                 ubuf.uio_segflg = UIO_USERSPACE;
461                 ubuf.uio_td = td;
462                 ubuf.uio_resid = s->count;
463                 ubuf.uio_offset = 0;
464                 ubuf.uio_rw = UIO_READ;
465                 error = iicuio_move(priv, &ubuf, s->last);
466                 break;
467
468         case I2CRDWR:
469                 /*
470                  * The rdwr list should be a self-contained set of
471                  * transactions.  Fail if another transaction is in progress.
472                  */
473                 if (priv->started) {
474                         error = EINVAL;
475                         break;
476                 }
477
478                 error = iicrdwr(priv, (struct iic_rdwr_data *)data, flags);
479
480                 break;
481
482         case I2CRPTSTART:
483                 if (!priv->started) {
484                         error = EINVAL;
485                         break;
486                 }
487                 error = iicbus_repeated_start(parent, s->slave, 0);
488                 break;
489
490         case I2CSADDR:
491                 priv->addr = *((uint8_t*)data);
492                 break;
493
494         default:
495                 error = ENOTTY;
496         }
497
498         IIC_UNLOCK(priv);
499         return (error);
500 }
501
502 DRIVER_MODULE(iic, iicbus, iic_driver, iic_devclass, 0, 0);
503 MODULE_DEPEND(iic, iicbus, IICBUS_MINVER, IICBUS_PREFVER, IICBUS_MAXVER);
504 MODULE_VERSION(iic, 1);