Annotation of src/sys/dev/i2c/i2c.c, Revision 1.47
1.47 ! riastrad 1: /* $NetBSD: i2c.c,v 1.46 2015/01/22 17:56:35 jakllsch Exp $ */
1.1 thorpej 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:
1.45 jmcneill 38: #ifdef _KERNEL_OPT
39: #include "opt_i2c.h"
40: #endif
41:
1.18 lukem 42: #include <sys/cdefs.h>
1.47 ! riastrad 43: __KERNEL_RCSID(0, "$NetBSD: i2c.c,v 1.46 2015/01/22 17:56:35 jakllsch Exp $");
1.18 lukem 44:
1.1 thorpej 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>
1.11 jmcneill 50: #include <sys/malloc.h>
1.34 jmcneill 51: #include <sys/kmem.h>
1.11 jmcneill 52: #include <sys/kthread.h>
53: #include <sys/proc.h>
54: #include <sys/kernel.h>
1.32 jmcneill 55: #include <sys/fcntl.h>
1.28 mbalmer 56: #include <sys/module.h>
1.1 thorpej 57:
58: #include <dev/i2c/i2cvar.h>
59:
60: #include "locators.h"
61:
1.45 jmcneill 62: #ifndef I2C_MAX_ADDR
1.27 pgoyette 63: #define I2C_MAX_ADDR 0x3ff /* 10-bit address, max */
1.45 jmcneill 64: #endif
1.27 pgoyette 65:
1.1 thorpej 66: struct iic_softc {
67: i2c_tag_t sc_tag;
1.6 jmcneill 68: int sc_type;
1.27 pgoyette 69: device_t sc_devices[I2C_MAX_ADDR + 1];
1.1 thorpej 70: };
71:
1.31 jmcneill 72: static dev_type_open(iic_open);
73: static dev_type_close(iic_close);
74: static dev_type_ioctl(iic_ioctl);
75:
76: const struct cdevsw iic_cdevsw = {
1.43 dholland 77: .d_open = iic_open,
78: .d_close = iic_close,
79: .d_read = noread,
80: .d_write = nowrite,
81: .d_ioctl = iic_ioctl,
82: .d_stop = nostop,
83: .d_tty = notty,
84: .d_poll = nopoll,
85: .d_mmap = nommap,
86: .d_kqfilter = nokqfilter,
1.44 dholland 87: .d_discard = nodiscard,
1.43 dholland 88: .d_flag = D_OTHER
1.31 jmcneill 89: };
90:
91: extern struct cfdriver iic_cd;
92:
1.11 jmcneill 93: static void iic_smbus_intr_thread(void *);
1.24 martin 94: static void iic_fill_compat(struct i2c_attach_args*, const char*,
95: size_t, char **);
1.11 jmcneill 96:
1.1 thorpej 97: static int
1.24 martin 98: iic_print_direct(void *aux, const char *pnp)
99: {
100: struct i2c_attach_args *ia = aux;
101:
102: if (pnp != NULL)
103: aprint_normal("%s at %s addr 0x%02x", ia->ia_name, pnp,
104: ia->ia_addr);
105: else
106: aprint_normal(" addr 0x%02x", ia->ia_addr);
107:
108: return UNCONF;
109: }
110:
111: static int
1.10 christos 112: iic_print(void *aux, const char *pnp)
1.1 thorpej 113: {
114: struct i2c_attach_args *ia = aux;
115:
1.6 jmcneill 116: if (ia->ia_addr != (i2c_addr_t)-1)
117: aprint_normal(" addr 0x%x", ia->ia_addr);
1.1 thorpej 118:
1.30 mbalmer 119: return UNCONF;
1.1 thorpej 120: }
121:
122: static int
1.20 xtraeme 123: iic_search(device_t parent, cfdata_t cf, const int *ldesc, void *aux)
1.1 thorpej 124: {
1.20 xtraeme 125: struct iic_softc *sc = device_private(parent);
1.1 thorpej 126: struct i2c_attach_args ia;
127:
128: ia.ia_tag = sc->sc_tag;
129: ia.ia_size = cf->cf_loc[IICCF_SIZE];
1.6 jmcneill 130: ia.ia_type = sc->sc_type;
1.1 thorpej 131:
1.25 njoly 132: ia.ia_name = NULL;
133: ia.ia_ncompat = 0;
134: ia.ia_compat = NULL;
135:
1.40 soren 136: for (ia.ia_addr = 0; ia.ia_addr <= I2C_MAX_ADDR; ia.ia_addr++) {
137: if (sc->sc_devices[ia.ia_addr] != NULL)
138: continue;
139:
140: if (cf->cf_loc[IICCF_ADDR] != -1 &&
141: cf->cf_loc[IICCF_ADDR] != ia.ia_addr)
142: continue;
143:
144: if (config_match(parent, cf, &ia) > 0)
1.27 pgoyette 145: sc->sc_devices[ia.ia_addr] =
146: config_attach(parent, cf, &ia, iic_print);
147: }
1.40 soren 148:
1.30 mbalmer 149: return 0;
1.1 thorpej 150: }
151:
1.27 pgoyette 152: static void
153: iic_child_detach(device_t parent, device_t child)
154: {
155: struct iic_softc *sc = device_private(parent);
156: int i;
157:
158: for (i = 0; i <= I2C_MAX_ADDR; i++)
159: if (sc->sc_devices[i] == child) {
160: sc->sc_devices[i] = NULL;
161: break;
1.40 soren 162: }
1.27 pgoyette 163: }
164:
1.1 thorpej 165: static int
1.26 jmcneill 166: iic_rescan(device_t self, const char *ifattr, const int *locators)
167: {
168: config_search_ia(iic_search, self, ifattr, NULL);
169: return 0;
170: }
171:
172: static int
1.20 xtraeme 173: iic_match(device_t parent, cfdata_t cf, void *aux)
1.1 thorpej 174: {
175:
1.30 mbalmer 176: return 1;
1.1 thorpej 177: }
178:
179: static void
1.20 xtraeme 180: iic_attach(device_t parent, device_t self, void *aux)
1.1 thorpej 181: {
1.7 thorpej 182: struct iic_softc *sc = device_private(self);
1.1 thorpej 183: struct i2cbus_attach_args *iba = aux;
1.24 martin 184: prop_array_t child_devices;
1.42 jdc 185: prop_dictionary_t props;
1.24 martin 186: char *buf;
1.14 ad 187: i2c_tag_t ic;
188: int rv;
1.42 jdc 189: bool indirect_config;
1.1 thorpej 190:
1.33 jmcneill 191: aprint_naive("\n");
1.1 thorpej 192: aprint_normal(": I2C bus\n");
193:
194: sc->sc_tag = iba->iba_tag;
1.6 jmcneill 195: sc->sc_type = iba->iba_type;
1.14 ad 196: ic = sc->sc_tag;
1.19 cegger 197: ic->ic_devname = device_xname(self);
1.11 jmcneill 198:
1.13 jmcneill 199: LIST_INIT(&(sc->sc_tag->ic_list));
200: LIST_INIT(&(sc->sc_tag->ic_proc_list));
1.14 ad 201:
1.33 jmcneill 202: rv = kthread_create(PRI_NONE, KTHREAD_MUSTJOIN, NULL,
203: iic_smbus_intr_thread, ic, &ic->ic_intr_thread,
204: "%s", ic->ic_devname);
1.14 ad 205: if (rv)
1.20 xtraeme 206: aprint_error_dev(self, "unable to create intr thread\n");
1.1 thorpej 207:
1.17 jmcneill 208: if (!pmf_device_register(self, NULL, NULL))
209: aprint_error_dev(self, "couldn't establish power handler\n");
210:
1.42 jdc 211: props = device_properties(parent);
212: if (!prop_dictionary_get_bool(props, "i2c-indirect-config",
213: &indirect_config))
214: indirect_config = true;
215: child_devices = prop_dictionary_get(props, "i2c-child-devices");
1.24 martin 216: if (child_devices) {
217: unsigned int i, count;
218: prop_dictionary_t dev;
219: prop_data_t cdata;
220: uint32_t addr, size;
221: uint64_t cookie;
222: const char *name;
223: struct i2c_attach_args ia;
224: int loc[2];
225:
226: memset(loc, 0, sizeof loc);
227: count = prop_array_count(child_devices);
228: for (i = 0; i < count; i++) {
229: dev = prop_array_get(child_devices, i);
230: if (!dev) continue;
231: if (!prop_dictionary_get_cstring_nocopy(
232: dev, "name", &name))
233: continue;
234: if (!prop_dictionary_get_uint32(dev, "addr", &addr))
235: continue;
236: if (!prop_dictionary_get_uint64(dev, "cookie", &cookie))
237: cookie = 0;
238: loc[0] = addr;
239: if (prop_dictionary_get_uint32(dev, "size", &size))
240: loc[1] = size;
241: else
242: loc[1] = -1;
243:
244: memset(&ia, 0, sizeof ia);
245: ia.ia_addr = addr;
246: ia.ia_type = sc->sc_type;
247: ia.ia_tag = ic;
248: ia.ia_name = name;
249: ia.ia_cookie = cookie;
1.39 jdc 250: ia.ia_size = size;
1.24 martin 251:
252: buf = NULL;
253: cdata = prop_dictionary_get(dev, "compatible");
254: if (cdata)
255: iic_fill_compat(&ia,
256: prop_data_data_nocopy(cdata),
257: prop_data_size(cdata), &buf);
258:
1.33 jmcneill 259: if (addr > I2C_MAX_ADDR) {
260: aprint_error_dev(self,
261: "WARNING: ignoring bad device address "
262: "@ 0x%02x\n", addr);
263: } else if (sc->sc_devices[addr] == NULL) {
264: sc->sc_devices[addr] =
265: config_found_sm_loc(self, "iic", loc, &ia,
266: iic_print_direct, NULL);
267: }
1.24 martin 268:
269: if (ia.ia_compat)
270: free(ia.ia_compat, M_TEMP);
271: if (buf)
272: free(buf, M_TEMP);
273: }
1.42 jdc 274: } else if (indirect_config) {
1.24 martin 275: /*
276: * Attach all i2c devices described in the kernel
277: * configuration file.
278: */
1.26 jmcneill 279: iic_rescan(self, "iic", NULL);
1.24 martin 280: }
1.1 thorpej 281: }
282:
1.33 jmcneill 283: static int
284: iic_detach(device_t self, int flags)
285: {
286: struct iic_softc *sc = device_private(self);
287: i2c_tag_t ic = sc->sc_tag;
288: int i, error;
289: void *hdl;
290:
291: for (i = 0; i <= I2C_MAX_ADDR; i++) {
292: if (sc->sc_devices[i]) {
293: error = config_detach(sc->sc_devices[i], flags);
294: if (error)
295: return error;
296: }
297: }
298:
299: if (ic->ic_running) {
300: ic->ic_running = 0;
301: wakeup(ic);
302: kthread_join(ic->ic_intr_thread);
303: }
304:
305: if (!LIST_EMPTY(&ic->ic_list)) {
306: device_printf(self, "WARNING: intr handler list not empty\n");
307: while (!LIST_EMPTY(&ic->ic_list)) {
308: hdl = LIST_FIRST(&ic->ic_list);
309: iic_smbus_intr_disestablish(ic, hdl);
310: }
311: }
312: if (!LIST_EMPTY(&ic->ic_proc_list)) {
313: device_printf(self, "WARNING: proc handler list not empty\n");
314: while (!LIST_EMPTY(&ic->ic_proc_list)) {
315: hdl = LIST_FIRST(&ic->ic_proc_list);
316: iic_smbus_intr_disestablish_proc(ic, hdl);
317: }
318: }
319:
320: pmf_device_deregister(self);
321:
322: return 0;
323: }
324:
1.11 jmcneill 325: static void
1.14 ad 326: iic_smbus_intr_thread(void *aux)
1.11 jmcneill 327: {
328: i2c_tag_t ic;
329: struct ic_intr_list *il;
330:
331: ic = (i2c_tag_t)aux;
332: ic->ic_running = 1;
333: ic->ic_pending = 0;
334:
335: while (ic->ic_running) {
336: if (ic->ic_pending == 0)
1.41 martin 337: tsleep(ic, PZERO, "iicintr", hz);
1.11 jmcneill 338: if (ic->ic_pending > 0) {
339: LIST_FOREACH(il, &(ic->ic_proc_list), il_next) {
340: (*il->il_intr)(il->il_intrarg);
341: }
342: ic->ic_pending--;
343: }
344: }
345:
346: kthread_exit(0);
347: }
348:
349: void *
350: iic_smbus_intr_establish(i2c_tag_t ic, int (*intr)(void *), void *intrarg)
351: {
352: struct ic_intr_list *il;
353:
354: il = malloc(sizeof(struct ic_intr_list), M_DEVBUF, M_WAITOK);
355: if (il == NULL)
356: return NULL;
1.28 mbalmer 357:
1.11 jmcneill 358: il->il_intr = intr;
359: il->il_intrarg = intrarg;
360:
361: LIST_INSERT_HEAD(&(ic->ic_list), il, il_next);
362:
363: return il;
364: }
365:
366: void
367: iic_smbus_intr_disestablish(i2c_tag_t ic, void *hdl)
368: {
369: struct ic_intr_list *il;
370:
371: il = (struct ic_intr_list *)hdl;
372:
373: LIST_REMOVE(il, il_next);
374: free(il, M_DEVBUF);
375:
376: return;
377: }
378:
379: void *
380: iic_smbus_intr_establish_proc(i2c_tag_t ic, int (*intr)(void *), void *intrarg)
381: {
382: struct ic_intr_list *il;
383:
384: il = malloc(sizeof(struct ic_intr_list), M_DEVBUF, M_WAITOK);
385: if (il == NULL)
386: return NULL;
1.28 mbalmer 387:
1.11 jmcneill 388: il->il_intr = intr;
389: il->il_intrarg = intrarg;
390:
391: LIST_INSERT_HEAD(&(ic->ic_proc_list), il, il_next);
392:
393: return il;
394: }
395:
396: void
397: iic_smbus_intr_disestablish_proc(i2c_tag_t ic, void *hdl)
398: {
399: struct ic_intr_list *il;
400:
401: il = (struct ic_intr_list *)hdl;
402:
403: LIST_REMOVE(il, il_next);
404: free(il, M_DEVBUF);
405:
406: return;
407: }
408:
409: int
410: iic_smbus_intr(i2c_tag_t ic)
411: {
412: struct ic_intr_list *il;
413:
414: LIST_FOREACH(il, &(ic->ic_list), il_next) {
415: (*il->il_intr)(il->il_intrarg);
416: }
417:
418: ic->ic_pending++;
419: wakeup(ic);
420:
421: return 1;
422: }
423:
1.24 martin 424: static void
425: iic_fill_compat(struct i2c_attach_args *ia, const char *compat, size_t len,
426: char **buffer)
427: {
428: int count, i;
429: const char *c, *start, **ptr;
430:
431: *buffer = NULL;
432: for (i = count = 0, c = compat; i < len; i++, c++)
433: if (*c == 0)
434: count++;
435: count += 2;
436: ptr = malloc(sizeof(char*)*count, M_TEMP, M_WAITOK);
437: if (!ptr) return;
438:
439: for (i = count = 0, start = c = compat; i < len; i++, c++) {
440: if (*c == 0) {
441: ptr[count++] = start;
442: start = c+1;
443: }
444: }
445: if (start < compat+len) {
446: /* last string not 0 terminated */
447: size_t l = c-start;
448: *buffer = malloc(l+1, M_TEMP, M_WAITOK);
449: memcpy(*buffer, start, l);
450: (*buffer)[l] = 0;
451: ptr[count++] = *buffer;
452: }
453: ptr[count] = NULL;
454:
455: ia->ia_compat = ptr;
456: ia->ia_ncompat = count;
457: }
458:
459: int
460: iic_compat_match(struct i2c_attach_args *ia, const char ** compats)
461: {
462: int i;
463:
464: for (; compats && *compats; compats++) {
465: for (i = 0; i < ia->ia_ncompat; i++) {
466: if (strcmp(*compats, ia->ia_compat[i]) == 0)
467: return 1;
468: }
469: }
470: return 0;
471: }
472:
1.31 jmcneill 473: static int
474: iic_open(dev_t dev, int flag, int fmt, lwp_t *l)
475: {
476: struct iic_softc *sc = device_lookup_private(&iic_cd, minor(dev));
477:
478: if (sc == NULL)
479: return ENXIO;
480:
481: return 0;
482: }
483:
484: static int
485: iic_close(dev_t dev, int flag, int fmt, lwp_t *l)
486: {
487: return 0;
488: }
489:
490: static int
1.32 jmcneill 491: iic_ioctl_exec(struct iic_softc *sc, i2c_ioctl_exec_t *iie, int flag)
1.31 jmcneill 492: {
493: i2c_tag_t ic = sc->sc_tag;
494: uint8_t buf[I2C_EXEC_MAX_BUFLEN];
1.34 jmcneill 495: void *cmd = NULL;
1.31 jmcneill 496: int error;
497:
498: /* Validate parameters */
499: if (iie->iie_addr > I2C_MAX_ADDR)
500: return EINVAL;
501: if (iie->iie_cmdlen > I2C_EXEC_MAX_CMDLEN ||
502: iie->iie_buflen > I2C_EXEC_MAX_BUFLEN)
503: return EINVAL;
504: if (iie->iie_cmd != NULL && iie->iie_cmdlen == 0)
505: return EINVAL;
506: if (iie->iie_buf != NULL && iie->iie_buflen == 0)
507: return EINVAL;
1.32 jmcneill 508: if (I2C_OP_WRITE_P(iie->iie_op) && (flag & FWRITE) == 0)
509: return EBADF;
1.31 jmcneill 510:
511: #if 0
512: /* Disallow userspace access to devices that have drivers attached. */
513: if (sc->sc_devices[iie->iie_addr] != NULL)
514: return EBUSY;
515: #endif
516:
517: if (iie->iie_cmd != NULL) {
1.34 jmcneill 518: cmd = kmem_alloc(iie->iie_cmdlen, KM_SLEEP);
519: if (cmd == NULL)
520: return ENOMEM;
1.31 jmcneill 521: error = copyin(iie->iie_cmd, cmd, iie->iie_cmdlen);
1.34 jmcneill 522: if (error) {
523: kmem_free(cmd, iie->iie_cmdlen);
1.31 jmcneill 524: return error;
1.34 jmcneill 525: }
1.31 jmcneill 526: }
527:
1.46 jakllsch 528: if (iie->iie_buf != NULL && I2C_OP_WRITE_P(iie->iie_op)) {
529: error = copyin(iie->iie_buf, buf, iie->iie_buflen);
530: if (error) {
1.47 ! riastrad 531: if (cmd)
! 532: kmem_free(cmd, iie->iie_cmdlen);
1.46 jakllsch 533: return error;
534: }
535: }
536:
1.31 jmcneill 537: iic_acquire_bus(ic, 0);
538: error = iic_exec(ic, iie->iie_op, iie->iie_addr, cmd, iie->iie_cmdlen,
539: buf, iie->iie_buflen, 0);
540: iic_release_bus(ic, 0);
541:
1.36 jmcneill 542: /*
543: * Some drivers return error codes on failure, and others return -1.
544: */
545: if (error < 0)
546: error = EIO;
547:
1.34 jmcneill 548: if (cmd)
549: kmem_free(cmd, iie->iie_cmdlen);
550:
1.31 jmcneill 551: if (error)
552: return error;
553:
1.46 jakllsch 554: if (iie->iie_buf != NULL && I2C_OP_READ_P(iie->iie_op))
1.31 jmcneill 555: error = copyout(buf, iie->iie_buf, iie->iie_buflen);
556:
557: return error;
558: }
559:
560: static int
561: iic_ioctl(dev_t dev, u_long cmd, void *data, int flag, lwp_t *l)
562: {
563: struct iic_softc *sc = device_lookup_private(&iic_cd, minor(dev));
564:
565: if (sc == NULL)
566: return ENXIO;
567:
568: switch (cmd) {
569: case I2C_IOCTL_EXEC:
1.32 jmcneill 570: return iic_ioctl_exec(sc, (i2c_ioctl_exec_t *)data, flag);
1.31 jmcneill 571: default:
572: return ENODEV;
573: }
574: }
575:
1.24 martin 576:
1.26 jmcneill 577: CFATTACH_DECL2_NEW(iic, sizeof(struct iic_softc),
1.33 jmcneill 578: iic_match, iic_attach, iic_detach, NULL, iic_rescan, iic_child_detach);
1.28 mbalmer 579:
580: MODULE(MODULE_CLASS_DRIVER, iic, NULL);
581:
582: #ifdef _MODULE
583: #include "ioconf.c"
584: #endif
585:
586: static int
587: iic_modcmd(modcmd_t cmd, void *opaque)
588: {
589: int error;
590:
591: error = 0;
592: switch (cmd) {
593: case MODULE_CMD_INIT:
594: #ifdef _MODULE
595: error = config_init_component(cfdriver_ioconf_iic,
596: cfattach_ioconf_iic, cfdata_ioconf_iic);
597: if (error)
598: aprint_error("%s: unable to init component\n",
599: iic_cd.cd_name);
600: #endif
601: break;
602: case MODULE_CMD_FINI:
603: #ifdef _MODULE
604: config_fini_component(cfdriver_ioconf_iic,
605: cfattach_ioconf_iic, cfdata_ioconf_iic);
606: #endif
607: break;
608: default:
609: error = ENOTTY;
610: }
611: return error;
612: }
CVSweb <webmaster@jp.NetBSD.org>