1 /* $NetBSD: i2c.c,v 1.54 2016/07/23 18:00:01 jakllsch Exp $ */
2
3 /*
4 * Copyright (c) 2003 Wasabi Systems, Inc.
5 * All rights reserved.
6 *
7 * Written by Jason R. Thorpe for Wasabi Systems, Inc.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed for the NetBSD Project by
20 * Wasabi Systems, Inc.
21 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
22 * or promote products derived from this software without specific prior
23 * written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
36 */
37
38 #ifdef _KERNEL_OPT
39 #include "opt_i2c.h"
40 #endif
41
42 #include <sys/cdefs.h>
43 __KERNEL_RCSID(0, "$NetBSD: i2c.c,v 1.54 2016/07/23 18:00:01 jakllsch Exp $");
44
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/device.h>
48 #include <sys/event.h>
49 #include <sys/conf.h>
50 #include <sys/malloc.h>
51 #include <sys/kmem.h>
52 #include <sys/kthread.h>
53 #include <sys/proc.h>
54 #include <sys/kernel.h>
55 #include <sys/fcntl.h>
56 #include <sys/module.h>
57 #include <sys/once.h>
58 #include <sys/mutex.h>
59
60 #include <dev/i2c/i2cvar.h>
61
62 #include "locators.h"
63
64 #ifndef I2C_MAX_ADDR
65 #define I2C_MAX_ADDR 0x3ff /* 10-bit address, max */
66 #endif
67
68 struct iic_softc {
69 i2c_tag_t sc_tag;
70 int sc_type;
71 device_t sc_devices[I2C_MAX_ADDR + 1];
72 };
73
74 static dev_type_open(iic_open);
75 static dev_type_close(iic_close);
76 static dev_type_ioctl(iic_ioctl);
77
78 int iic_init(void);
79
80 kmutex_t iic_mtx;
81 int iic_refcnt;
82
83 ONCE_DECL(iic_once);
84
85 const struct cdevsw iic_cdevsw = {
86 .d_open = iic_open,
87 .d_close = iic_close,
88 .d_read = noread,
89 .d_write = nowrite,
90 .d_ioctl = iic_ioctl,
91 .d_stop = nostop,
92 .d_tty = notty,
93 .d_poll = nopoll,
94 .d_mmap = nommap,
95 .d_kqfilter = nokqfilter,
96 .d_discard = nodiscard,
97 .d_flag = D_OTHER
98 };
99
100 extern struct cfdriver iic_cd;
101
102 static void iic_smbus_intr_thread(void *);
103 static void iic_fill_compat(struct i2c_attach_args*, const char*,
104 size_t, char **);
105
106 static int
iic_print_direct(void * aux,const char * pnp)107 iic_print_direct(void *aux, const char *pnp)
108 {
109 struct i2c_attach_args *ia = aux;
110
111 if (pnp != NULL)
112 aprint_normal("%s at %s addr 0x%02x", ia->ia_name, pnp,
113 ia->ia_addr);
114 else
115 aprint_normal(" addr 0x%02x", ia->ia_addr);
116
117 return UNCONF;
118 }
119
120 static int
iic_print(void * aux,const char * pnp)121 iic_print(void *aux, const char *pnp)
122 {
123 struct i2c_attach_args *ia = aux;
124
125 if (ia->ia_addr != (i2c_addr_t)-1)
126 aprint_normal(" addr 0x%x", ia->ia_addr);
127
128 return UNCONF;
129 }
130
131 static int
iic_search(device_t parent,cfdata_t cf,const int * ldesc,void * aux)132 iic_search(device_t parent, cfdata_t cf, const int *ldesc, void *aux)
133 {
134 struct iic_softc *sc = device_private(parent);
135 struct i2c_attach_args ia;
136
137 ia.ia_tag = sc->sc_tag;
138 ia.ia_size = cf->cf_loc[IICCF_SIZE];
139 ia.ia_type = sc->sc_type;
140
141 ia.ia_name = NULL;
142 ia.ia_ncompat = 0;
143 ia.ia_compat = NULL;
144
145 for (ia.ia_addr = 0; ia.ia_addr <= I2C_MAX_ADDR; ia.ia_addr++) {
146 if (sc->sc_devices[ia.ia_addr] != NULL)
147 continue;
148
149 if (cf->cf_loc[IICCF_ADDR] != -1 &&
150 cf->cf_loc[IICCF_ADDR] != ia.ia_addr)
151 continue;
152
153 if (config_match(parent, cf, &ia) > 0)
154 sc->sc_devices[ia.ia_addr] =
155 config_attach(parent, cf, &ia, iic_print);
156 }
157
158 return 0;
159 }
160
161 static void
iic_child_detach(device_t parent,device_t child)162 iic_child_detach(device_t parent, device_t child)
163 {
164 struct iic_softc *sc = device_private(parent);
165 int i;
166
167 for (i = 0; i <= I2C_MAX_ADDR; i++)
168 if (sc->sc_devices[i] == child) {
169 sc->sc_devices[i] = NULL;
170 break;
171 }
172 }
173
174 static int
iic_rescan(device_t self,const char * ifattr,const int * locators)175 iic_rescan(device_t self, const char *ifattr, const int *locators)
176 {
177 config_search_ia(iic_search, self, ifattr, NULL);
178 return 0;
179 }
180
181 static int
iic_match(device_t parent,cfdata_t cf,void * aux)182 iic_match(device_t parent, cfdata_t cf, void *aux)
183 {
184
185 return 1;
186 }
187
188 static void
iic_attach(device_t parent,device_t self,void * aux)189 iic_attach(device_t parent, device_t self, void *aux)
190 {
191 struct iic_softc *sc = device_private(self);
192 struct i2cbus_attach_args *iba = aux;
193 prop_array_t child_devices;
194 prop_dictionary_t props;
195 char *buf;
196 i2c_tag_t ic;
197 int rv;
198 bool indirect_config;
199
200 aprint_naive("\n");
201 aprint_normal(": I2C bus\n");
202
203 sc->sc_tag = iba->iba_tag;
204 sc->sc_type = iba->iba_type;
205 ic = sc->sc_tag;
206 ic->ic_devname = device_xname(self);
207
208 LIST_INIT(&(sc->sc_tag->ic_list));
209 LIST_INIT(&(sc->sc_tag->ic_proc_list));
210
211 rv = kthread_create(PRI_NONE, KTHREAD_MUSTJOIN, NULL,
212 iic_smbus_intr_thread, ic, &ic->ic_intr_thread,
213 "%s", ic->ic_devname);
214 if (rv)
215 aprint_error_dev(self, "unable to create intr thread\n");
216
217 if (!pmf_device_register(self, NULL, NULL))
218 aprint_error_dev(self, "couldn't establish power handler\n");
219
220 if (iba->iba_child_devices) {
221 child_devices = iba->iba_child_devices;
222 indirect_config = false;
223 } else {
224 props = device_properties(parent);
225 if (!prop_dictionary_get_bool(props, "i2c-indirect-config",
226 &indirect_config))
227 indirect_config = true;
228 child_devices = prop_dictionary_get(props, "i2c-child-devices");
229 }
230
231 if (child_devices) {
232 unsigned int i, count;
233 prop_dictionary_t dev;
234 prop_data_t cdata;
235 uint32_t addr, size;
236 uint64_t cookie;
237 const char *name;
238 struct i2c_attach_args ia;
239 int loc[IICCF_NLOCS];
240
241 memset(loc, 0, sizeof loc);
242 count = prop_array_count(child_devices);
243 for (i = 0; i < count; i++) {
244 dev = prop_array_get(child_devices, i);
245 if (!dev) continue;
246 if (!prop_dictionary_get_cstring_nocopy(
247 dev, "name", &name))
248 continue;
249 if (!prop_dictionary_get_uint32(dev, "addr", &addr))
250 continue;
251 if (!prop_dictionary_get_uint64(dev, "cookie", &cookie))
252 cookie = 0;
253 loc[IICCF_ADDR] = addr;
254 if (prop_dictionary_get_uint32(dev, "size", &size))
255 loc[IICCF_SIZE] = size;
256 else
257 size = loc[IICCF_SIZE] = IICCF_SIZE_DEFAULT;
258
259 memset(&ia, 0, sizeof ia);
260 ia.ia_addr = addr;
261 ia.ia_type = sc->sc_type;
262 ia.ia_tag = ic;
263 ia.ia_name = name;
264 ia.ia_cookie = cookie;
265 ia.ia_size = size;
266
267 buf = NULL;
268 cdata = prop_dictionary_get(dev, "compatible");
269 if (cdata)
270 iic_fill_compat(&ia,
271 prop_data_data_nocopy(cdata),
272 prop_data_size(cdata), &buf);
273
274 if (addr > I2C_MAX_ADDR) {
275 aprint_error_dev(self,
276 "WARNING: ignoring bad device address "
277 "@ 0x%02x\n", addr);
278 } else if (sc->sc_devices[addr] == NULL) {
279 sc->sc_devices[addr] =
280 config_found_sm_loc(self, "iic", loc, &ia,
281 iic_print_direct, NULL);
282 }
283
284 if (ia.ia_compat)
285 free(ia.ia_compat, M_TEMP);
286 if (buf)
287 free(buf, M_TEMP);
288 }
289 } else if (indirect_config) {
290 /*
291 * Attach all i2c devices described in the kernel
292 * configuration file.
293 */
294 iic_rescan(self, "iic", NULL);
295 }
296 }
297
298 static int
iic_detach(device_t self,int flags)299 iic_detach(device_t self, int flags)
300 {
301 struct iic_softc *sc = device_private(self);
302 i2c_tag_t ic = sc->sc_tag;
303 int i, error;
304 void *hdl;
305
306 for (i = 0; i <= I2C_MAX_ADDR; i++) {
307 if (sc->sc_devices[i]) {
308 error = config_detach(sc->sc_devices[i], flags);
309 if (error)
310 return error;
311 }
312 }
313
314 if (ic->ic_running) {
315 ic->ic_running = 0;
316 wakeup(ic);
317 kthread_join(ic->ic_intr_thread);
318 }
319
320 if (!LIST_EMPTY(&ic->ic_list)) {
321 device_printf(self, "WARNING: intr handler list not empty\n");
322 while (!LIST_EMPTY(&ic->ic_list)) {
323 hdl = LIST_FIRST(&ic->ic_list);
324 iic_smbus_intr_disestablish(ic, hdl);
325 }
326 }
327 if (!LIST_EMPTY(&ic->ic_proc_list)) {
328 device_printf(self, "WARNING: proc handler list not empty\n");
329 while (!LIST_EMPTY(&ic->ic_proc_list)) {
330 hdl = LIST_FIRST(&ic->ic_proc_list);
331 iic_smbus_intr_disestablish_proc(ic, hdl);
332 }
333 }
334
335 pmf_device_deregister(self);
336
337 return 0;
338 }
339
340 static void
iic_smbus_intr_thread(void * aux)341 iic_smbus_intr_thread(void *aux)
342 {
343 i2c_tag_t ic;
344 struct ic_intr_list *il;
345
346 ic = (i2c_tag_t)aux;
347 ic->ic_running = 1;
348 ic->ic_pending = 0;
349
350 while (ic->ic_running) {
351 if (ic->ic_pending == 0)
352 tsleep(ic, PZERO, "iicintr", hz);
353 if (ic->ic_pending > 0) {
354 LIST_FOREACH(il, &(ic->ic_proc_list), il_next) {
355 (*il->il_intr)(il->il_intrarg);
356 }
357 ic->ic_pending--;
358 }
359 }
360
361 kthread_exit(0);
362 }
363
364 void *
iic_smbus_intr_establish(i2c_tag_t ic,int (* intr)(void *),void * intrarg)365 iic_smbus_intr_establish(i2c_tag_t ic, int (*intr)(void *), void *intrarg)
366 {
367 struct ic_intr_list *il;
368
369 il = malloc(sizeof(struct ic_intr_list), M_DEVBUF, M_WAITOK);
370 if (il == NULL)
371 return NULL;
372
373 il->il_intr = intr;
374 il->il_intrarg = intrarg;
375
376 LIST_INSERT_HEAD(&(ic->ic_list), il, il_next);
377
378 return il;
379 }
380
381 void
iic_smbus_intr_disestablish(i2c_tag_t ic,void * hdl)382 iic_smbus_intr_disestablish(i2c_tag_t ic, void *hdl)
383 {
384 struct ic_intr_list *il;
385
386 il = (struct ic_intr_list *)hdl;
387
388 LIST_REMOVE(il, il_next);
389 free(il, M_DEVBUF);
390
391 return;
392 }
393
394 void *
iic_smbus_intr_establish_proc(i2c_tag_t ic,int (* intr)(void *),void * intrarg)395 iic_smbus_intr_establish_proc(i2c_tag_t ic, int (*intr)(void *), void *intrarg)
396 {
397 struct ic_intr_list *il;
398
399 il = malloc(sizeof(struct ic_intr_list), M_DEVBUF, M_WAITOK);
400 if (il == NULL)
401 return NULL;
402
403 il->il_intr = intr;
404 il->il_intrarg = intrarg;
405
406 LIST_INSERT_HEAD(&(ic->ic_proc_list), il, il_next);
407
408 return il;
409 }
410
411 void
iic_smbus_intr_disestablish_proc(i2c_tag_t ic,void * hdl)412 iic_smbus_intr_disestablish_proc(i2c_tag_t ic, void *hdl)
413 {
414 struct ic_intr_list *il;
415
416 il = (struct ic_intr_list *)hdl;
417
418 LIST_REMOVE(il, il_next);
419 free(il, M_DEVBUF);
420
421 return;
422 }
423
424 int
iic_smbus_intr(i2c_tag_t ic)425 iic_smbus_intr(i2c_tag_t ic)
426 {
427 struct ic_intr_list *il;
428
429 LIST_FOREACH(il, &(ic->ic_list), il_next) {
430 (*il->il_intr)(il->il_intrarg);
431 }
432
433 ic->ic_pending++;
434 wakeup(ic);
435
436 return 1;
437 }
438
439 static void
iic_fill_compat(struct i2c_attach_args * ia,const char * compat,size_t len,char ** buffer)440 iic_fill_compat(struct i2c_attach_args *ia, const char *compat, size_t len,
441 char **buffer)
442 {
443 int count, i;
444 const char *c, *start, **ptr;
445
446 *buffer = NULL;
447 for (i = count = 0, c = compat; i < len; i++, c++)
448 if (*c == 0)
449 count++;
450 count += 2;
451 ptr = malloc(sizeof(char*)*count, M_TEMP, M_WAITOK);
452 if (!ptr) return;
453
454 for (i = count = 0, start = c = compat; i < len; i++, c++) {
455 if (*c == 0) {
456 ptr[count++] = start;
457 start = c+1;
458 }
459 }
460 if (start < compat+len) {
461 /* last string not 0 terminated */
462 size_t l = c-start;
463 *buffer = malloc(l+1, M_TEMP, M_WAITOK);
464 memcpy(*buffer, start, l);
465 (*buffer)[l] = 0;
466 ptr[count++] = *buffer;
467 }
468 ptr[count] = NULL;
469
470 ia->ia_compat = ptr;
471 ia->ia_ncompat = count;
472 }
473
474 int
iic_compat_match(struct i2c_attach_args * ia,const char ** compats)475 iic_compat_match(struct i2c_attach_args *ia, const char ** compats)
476 {
477 int i;
478
479 for (; compats && *compats; compats++) {
480 for (i = 0; i < ia->ia_ncompat; i++) {
481 if (strcmp(*compats, ia->ia_compat[i]) == 0)
482 return 1;
483 }
484 }
485 return 0;
486 }
487
488 static int
iic_open(dev_t dev,int flag,int fmt,lwp_t * l)489 iic_open(dev_t dev, int flag, int fmt, lwp_t *l)
490 {
491 struct iic_softc *sc = device_lookup_private(&iic_cd, minor(dev));
492
493 mutex_enter(&iic_mtx);
494 if (sc == NULL) {
495 mutex_exit(&iic_mtx);
496 return ENXIO;
497 }
498 iic_refcnt++;
499 mutex_exit(&iic_mtx);
500
501 return 0;
502 }
503
504 static int
iic_close(dev_t dev,int flag,int fmt,lwp_t * l)505 iic_close(dev_t dev, int flag, int fmt, lwp_t *l)
506 {
507
508 mutex_enter(&iic_mtx);
509 iic_refcnt--;
510 mutex_exit(&iic_mtx);
511
512 return 0;
513 }
514
515 static int
iic_ioctl_exec(struct iic_softc * sc,i2c_ioctl_exec_t * iie,int flag)516 iic_ioctl_exec(struct iic_softc *sc, i2c_ioctl_exec_t *iie, int flag)
517 {
518 i2c_tag_t ic = sc->sc_tag;
519 uint8_t buf[I2C_EXEC_MAX_BUFLEN];
520 void *cmd = NULL;
521 int error;
522
523 /* Validate parameters */
524 if (iie->iie_addr > I2C_MAX_ADDR)
525 return EINVAL;
526 if (iie->iie_cmdlen > I2C_EXEC_MAX_CMDLEN ||
527 iie->iie_buflen > I2C_EXEC_MAX_BUFLEN)
528 return EINVAL;
529 if (iie->iie_cmd != NULL && iie->iie_cmdlen == 0)
530 return EINVAL;
531 if (iie->iie_buf != NULL && iie->iie_buflen == 0)
532 return EINVAL;
533 if (I2C_OP_WRITE_P(iie->iie_op) && (flag & FWRITE) == 0)
534 return EBADF;
535
536 #if 0
537 /* Disallow userspace access to devices that have drivers attached. */
538 if (sc->sc_devices[iie->iie_addr] != NULL)
539 return EBUSY;
540 #endif
541
542 if (iie->iie_cmd != NULL) {
543 cmd = kmem_alloc(iie->iie_cmdlen, KM_SLEEP);
544 if (cmd == NULL)
545 return ENOMEM;
546 error = copyin(iie->iie_cmd, cmd, iie->iie_cmdlen);
547 if (error)
548 goto out;
549 }
550
551 if (iie->iie_buf != NULL && I2C_OP_WRITE_P(iie->iie_op)) {
552 error = copyin(iie->iie_buf, buf, iie->iie_buflen);
553 if (error)
554 goto out;
555 }
556
557 iic_acquire_bus(ic, 0);
558 error = iic_exec(ic, iie->iie_op, iie->iie_addr, cmd, iie->iie_cmdlen,
559 buf, iie->iie_buflen, 0);
560 iic_release_bus(ic, 0);
561
562 /*
563 * Some drivers return error codes on failure, and others return -1.
564 */
565 if (error < 0)
566 error = EIO;
567
568 out:
569 if (cmd)
570 kmem_free(cmd, iie->iie_cmdlen);
571
572 if (error)
573 return error;
574
575 if (iie->iie_buf != NULL && I2C_OP_READ_P(iie->iie_op))
576 error = copyout(buf, iie->iie_buf, iie->iie_buflen);
577
578 return error;
579 }
580
581 static int
iic_ioctl(dev_t dev,u_long cmd,void * data,int flag,lwp_t * l)582 iic_ioctl(dev_t dev, u_long cmd, void *data, int flag, lwp_t *l)
583 {
584 struct iic_softc *sc = device_lookup_private(&iic_cd, minor(dev));
585
586 if (sc == NULL)
587 return ENXIO;
588
589 switch (cmd) {
590 case I2C_IOCTL_EXEC:
591 return iic_ioctl_exec(sc, (i2c_ioctl_exec_t *)data, flag);
592 default:
593 return ENODEV;
594 }
595 }
596
597
598 CFATTACH_DECL2_NEW(iic, sizeof(struct iic_softc),
599 iic_match, iic_attach, iic_detach, NULL, iic_rescan, iic_child_detach);
600
601 MODULE(MODULE_CLASS_DRIVER, iic, "i2cexec,i2c_bitbang");
602
603 #ifdef _MODULE
604 #include "ioconf.c"
605 #endif
606
607 int
iic_init(void)608 iic_init(void)
609 {
610
611 mutex_init(&iic_mtx, MUTEX_DEFAULT, IPL_NONE);
612 iic_refcnt = 0;
613 return 0;
614 }
615
616 static int
iic_modcmd(modcmd_t cmd,void * opaque)617 iic_modcmd(modcmd_t cmd, void *opaque)
618 {
619 #ifdef _MODULE
620 int bmajor, cmajor;
621 #endif
622 int error;
623
624 error = 0;
625 switch (cmd) {
626 case MODULE_CMD_INIT:
627 RUN_ONCE(&iic_once, iic_init);
628
629 #ifdef _MODULE
630 mutex_enter(&iic_mtx);
631 bmajor = cmajor = -1;
632 error = devsw_attach("iic", NULL, &bmajor,
633 &iic_cdevsw, &cmajor);
634 if (error != 0) {
635 mutex_exit(&iic_mtx);
636 break;
637 }
638 error = config_init_component(cfdriver_ioconf_iic,
639 cfattach_ioconf_iic, cfdata_ioconf_iic);
640 if (error) {
641 aprint_error("%s: unable to init component\n",
642 iic_cd.cd_name);
643 (void)devsw_detach(NULL, &iic_cdevsw);
644 }
645 mutex_exit(&iic_mtx);
646 #endif
647 break;
648 case MODULE_CMD_FINI:
649 mutex_enter(&iic_mtx);
650 if (iic_refcnt != 0) {
651 mutex_exit(&iic_mtx);
652 return EBUSY;
653 }
654 #ifdef _MODULE
655 error = config_fini_component(cfdriver_ioconf_iic,
656 cfattach_ioconf_iic, cfdata_ioconf_iic);
657 if (error != 0) {
658 mutex_exit(&iic_mtx);
659 break;
660 }
661 error = devsw_detach(NULL, &iic_cdevsw);
662 if (error != 0)
663 config_init_component(cfdriver_ioconf_iic,
664 cfattach_ioconf_iic, cfdata_ioconf_iic);
665 #endif
666 mutex_exit(&iic_mtx);
667 break;
668 default:
669 error = ENOTTY;
670 }
671 return error;
672 }
673