Annotation of src/sys/dev/i2c/i2c.c, Revision 1.59
1.59 ! thorpej 1: /* $NetBSD: i2c.c,v 1.58 2018/05/15 02:02:18 thorpej 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.59 ! thorpej 43: __KERNEL_RCSID(0, "$NetBSD: i2c.c,v 1.58 2018/05/15 02:02:18 thorpej 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.50 pgoyette 57: #include <sys/once.h>
58: #include <sys/mutex.h>
1.1 thorpej 59:
60: #include <dev/i2c/i2cvar.h>
61:
1.56 riastrad 62: #include "ioconf.h"
1.1 thorpej 63: #include "locators.h"
64:
1.45 jmcneill 65: #ifndef I2C_MAX_ADDR
1.27 pgoyette 66: #define I2C_MAX_ADDR 0x3ff /* 10-bit address, max */
1.45 jmcneill 67: #endif
1.27 pgoyette 68:
1.1 thorpej 69: struct iic_softc {
1.59 ! thorpej 70: device_t sc_dev;
1.1 thorpej 71: i2c_tag_t sc_tag;
1.6 jmcneill 72: int sc_type;
1.27 pgoyette 73: device_t sc_devices[I2C_MAX_ADDR + 1];
1.1 thorpej 74: };
75:
1.31 jmcneill 76: static dev_type_open(iic_open);
77: static dev_type_close(iic_close);
78: static dev_type_ioctl(iic_ioctl);
79:
1.50 pgoyette 80: int iic_init(void);
81:
82: kmutex_t iic_mtx;
83: int iic_refcnt;
84:
85: ONCE_DECL(iic_once);
86:
1.31 jmcneill 87: const struct cdevsw iic_cdevsw = {
1.43 dholland 88: .d_open = iic_open,
89: .d_close = iic_close,
90: .d_read = noread,
91: .d_write = nowrite,
92: .d_ioctl = iic_ioctl,
93: .d_stop = nostop,
94: .d_tty = notty,
95: .d_poll = nopoll,
96: .d_mmap = nommap,
97: .d_kqfilter = nokqfilter,
1.44 dholland 98: .d_discard = nodiscard,
1.43 dholland 99: .d_flag = D_OTHER
1.31 jmcneill 100: };
101:
1.11 jmcneill 102: static void iic_smbus_intr_thread(void *);
1.24 martin 103: static void iic_fill_compat(struct i2c_attach_args*, const char*,
104: size_t, char **);
1.11 jmcneill 105:
1.1 thorpej 106: static int
1.24 martin 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
1.10 christos 121: iic_print(void *aux, const char *pnp)
1.1 thorpej 122: {
123: struct i2c_attach_args *ia = aux;
124:
1.58 thorpej 125: if (ia->ia_addr != (i2c_addr_t)IICCF_ADDR_DEFAULT)
1.6 jmcneill 126: aprint_normal(" addr 0x%x", ia->ia_addr);
1.1 thorpej 127:
1.30 mbalmer 128: return UNCONF;
1.1 thorpej 129: }
130:
1.59 ! thorpej 131: static bool
! 132: iic_is_special_address(i2c_addr_t addr)
! 133: {
! 134:
! 135: /*
! 136: * See: https://www.i2c-bus.org/addressing/
! 137: */
! 138:
! 139: /* General Call (read) / Start Byte (write) */
! 140: if (addr == 0x00)
! 141: return (true);
! 142:
! 143: /* CBUS Addresses */
! 144: if (addr == 0x01)
! 145: return (true);
! 146:
! 147: /* Reserved for Different Bus Formats */
! 148: if (addr == 0x02)
! 149: return (true);
! 150:
! 151: /* Reserved for future purposes */
! 152: if (addr == 0x03)
! 153: return (true);
! 154:
! 155: /* High Speed Master Code */
! 156: if ((addr & 0x7c) == 0x04)
! 157: return (true);
! 158:
! 159: /* 10-bit Slave Addressing prefix */
! 160: if ((addr & 0x7c) == 0x78)
! 161: return (true);
! 162:
! 163: /* Reserved for future purposes */
! 164: if ((addr & 0x7c) == 0x7c)
! 165: return (true);
! 166:
! 167: return (false);
! 168: }
! 169:
! 170: static int
! 171: iic_probe_none(struct iic_softc *sc,
! 172: const struct i2c_attach_args *ia, int flags)
! 173: {
! 174:
! 175: return (0);
! 176: }
! 177:
! 178: static int
! 179: iic_probe_smbus_quick_write(struct iic_softc *sc,
! 180: const struct i2c_attach_args *ia, int flags)
! 181: {
! 182: int error;
! 183:
! 184: if ((error = iic_acquire_bus(ia->ia_tag, flags)) == 0) {
! 185: error = iic_smbus_quick_write(ia->ia_tag, ia->ia_addr, flags);
! 186: }
! 187: (void) iic_release_bus(ia->ia_tag, flags);
! 188:
! 189: return (error);
! 190: }
! 191:
! 192: static int
! 193: iic_probe_smbus_receive_byte(struct iic_softc *sc,
! 194: const struct i2c_attach_args *ia, int flags)
! 195: {
! 196: int error;
! 197:
! 198: if ((error = iic_acquire_bus(ia->ia_tag, flags)) == 0) {
! 199: uint8_t dummy;
! 200:
! 201: error = iic_smbus_receive_byte(ia->ia_tag, ia->ia_addr,
! 202: &dummy, flags);
! 203: }
! 204: (void) iic_release_bus(ia->ia_tag, flags);
! 205:
! 206: return (error);
! 207: }
! 208:
! 209: static bool
! 210: iic_indirect_driver_is_whitelisted(struct iic_softc *sc, cfdata_t cf)
! 211: {
! 212: prop_object_iterator_t iter;
! 213: prop_array_t whitelist;
! 214: prop_string_t pstr;
! 215: prop_type_t ptype;
! 216: bool rv = false;
! 217:
! 218: whitelist = prop_dictionary_get(device_properties(sc->sc_dev),
! 219: I2C_PROP_INDIRECT_DEVICE_WHITELIST);
! 220: if (whitelist == NULL) {
! 221: /* No whitelist -> everything allowed */
! 222: return (true);
! 223: }
! 224:
! 225: if ((ptype = prop_object_type(whitelist)) != PROP_TYPE_ARRAY) {
! 226: aprint_error_dev(sc->sc_dev,
! 227: "invalid property type (%d) for '%s'; must be array (%d)\n",
! 228: ptype, I2C_PROP_INDIRECT_DEVICE_WHITELIST, PROP_TYPE_ARRAY);
! 229: return (false);
! 230: }
! 231:
! 232: iter = prop_array_iterator(whitelist);
! 233: while ((pstr = prop_object_iterator_next(iter)) != NULL) {
! 234: if (prop_string_equals_cstring(pstr, cf->cf_name)) {
! 235: rv = true;
! 236: break;
! 237: }
! 238: }
! 239: prop_object_iterator_release(iter);
! 240:
! 241: return (rv);
! 242: }
! 243:
1.1 thorpej 244: static int
1.20 xtraeme 245: iic_search(device_t parent, cfdata_t cf, const int *ldesc, void *aux)
1.1 thorpej 246: {
1.20 xtraeme 247: struct iic_softc *sc = device_private(parent);
1.1 thorpej 248: struct i2c_attach_args ia;
1.59 ! thorpej 249: int (*probe_func)(struct iic_softc *,
! 250: const struct i2c_attach_args *, int);
! 251: prop_string_t pstr;
! 252: i2c_addr_t first_addr, last_addr;
1.1 thorpej 253:
1.58 thorpej 254: /*
1.59 ! thorpej 255: * Before we do any more work, consult the allowed-driver
! 256: * white-list for this bus (if any).
1.58 thorpej 257: */
1.59 ! thorpej 258: if (iic_indirect_driver_is_whitelisted(sc, cf) == false)
! 259: return (0);
! 260:
! 261: /* default to "quick write". */
! 262: probe_func = iic_probe_smbus_quick_write;
! 263:
! 264: pstr = prop_dictionary_get(device_properties(sc->sc_dev),
! 265: I2C_PROP_INDIRECT_PROBE_STRATEGY);
! 266: if (pstr == NULL) {
! 267: /* Use the default. */
! 268: } else if (prop_string_equals_cstring(pstr,
! 269: I2C_PROBE_STRATEGY_QUICK_WRITE)) {
! 270: probe_func = iic_probe_smbus_quick_write;
! 271: } else if (prop_string_equals_cstring(pstr,
! 272: I2C_PROBE_STRATEGY_RECEIVE_BYTE)) {
! 273: probe_func = iic_probe_smbus_receive_byte;
! 274: } else if (prop_string_equals_cstring(pstr,
! 275: I2C_PROBE_STRATEGY_NONE)) {
! 276: probe_func = iic_probe_none;
! 277: } else {
! 278: aprint_error_dev(sc->sc_dev,
! 279: "unknown probe strategy '%s'; defaulting to '%s'\n",
! 280: prop_string_cstring_nocopy(pstr),
! 281: I2C_PROBE_STRATEGY_QUICK_WRITE);
! 282:
! 283: /* Use the default. */
! 284: }
1.58 thorpej 285:
1.1 thorpej 286: ia.ia_tag = sc->sc_tag;
287: ia.ia_size = cf->cf_loc[IICCF_SIZE];
1.6 jmcneill 288: ia.ia_type = sc->sc_type;
1.1 thorpej 289:
1.25 njoly 290: ia.ia_name = NULL;
291: ia.ia_ncompat = 0;
292: ia.ia_compat = NULL;
1.57 bouyer 293: ia.ia_prop = NULL;
1.25 njoly 294:
1.59 ! thorpej 295: if (cf->cf_loc[IICCF_ADDR] == IICCF_ADDR_DEFAULT) {
! 296: /*
! 297: * This particular config directive has
! 298: * wildcarded the address, so we will
! 299: * scan the entire bus for it.
! 300: */
! 301: first_addr = 0;
! 302: last_addr = I2C_MAX_ADDR;
! 303: } else {
! 304: /*
! 305: * This config directive hard-wires the i2c
! 306: * bus address for the device, so there is
! 307: * no need to go poking around at any other
! 308: * addresses.
! 309: */
! 310: if (cf->cf_loc[IICCF_ADDR] < 0 ||
! 311: cf->cf_loc[IICCF_ADDR] > I2C_MAX_ADDR) {
! 312: /* Invalid config directive! */
! 313: return (0);
! 314: }
! 315: first_addr = last_addr = cf->cf_loc[IICCF_ADDR];
! 316: }
! 317:
! 318: for (ia.ia_addr = first_addr; ia.ia_addr <= last_addr; ia.ia_addr++) {
! 319: int error, match_result;
! 320:
! 321: /*
! 322: * Skip I2C addresses that are reserved for
! 323: * special purposes.
! 324: */
! 325: if (iic_is_special_address(ia.ia_addr))
! 326: continue;
! 327:
! 328: /*
! 329: * Skip addresses where a device is already attached.
! 330: */
1.40 soren 331: if (sc->sc_devices[ia.ia_addr] != NULL)
332: continue;
333:
1.59 ! thorpej 334: /*
! 335: * Call the "match" routine for the device. If that
! 336: * returns success, then call the probe strategy
! 337: * function.
! 338: *
! 339: * We do it in this order because i2c devices tend
! 340: * to be found at a small number of possible addresses
! 341: * (e.g. read-time clocks that are only ever found at
! 342: * 0x68). This gives the driver a chance to skip any
! 343: * address that are not valid for the device, saving
! 344: * us from having to poke at the bus to see if anything
! 345: * is there.
! 346: */
! 347: match_result = config_match(parent, cf, &ia);
! 348: if (match_result <= 0)
! 349: continue;
! 350:
! 351: /*
! 352: * If the quality of the match by the driver was low
! 353: * (i.e. matched on being a valid address only, didn't
! 354: * perform any hardware probe), invoke our probe routine
! 355: * to see if it looks like something is really there.
! 356: */
! 357: if (match_result == I2C_MATCH_ADDRESS_ONLY &&
! 358: (error = (*probe_func)(sc, &ia, I2C_F_POLL)) != 0)
1.40 soren 359: continue;
360:
1.59 ! thorpej 361: sc->sc_devices[ia.ia_addr] =
! 362: config_attach(parent, cf, &ia, iic_print);
1.27 pgoyette 363: }
1.40 soren 364:
1.30 mbalmer 365: return 0;
1.1 thorpej 366: }
367:
1.27 pgoyette 368: static void
369: iic_child_detach(device_t parent, device_t child)
370: {
371: struct iic_softc *sc = device_private(parent);
372: int i;
373:
374: for (i = 0; i <= I2C_MAX_ADDR; i++)
375: if (sc->sc_devices[i] == child) {
376: sc->sc_devices[i] = NULL;
377: break;
1.40 soren 378: }
1.27 pgoyette 379: }
380:
1.1 thorpej 381: static int
1.26 jmcneill 382: iic_rescan(device_t self, const char *ifattr, const int *locators)
383: {
384: config_search_ia(iic_search, self, ifattr, NULL);
385: return 0;
386: }
387:
388: static int
1.20 xtraeme 389: iic_match(device_t parent, cfdata_t cf, void *aux)
1.1 thorpej 390: {
391:
1.30 mbalmer 392: return 1;
1.1 thorpej 393: }
394:
395: static void
1.20 xtraeme 396: iic_attach(device_t parent, device_t self, void *aux)
1.1 thorpej 397: {
1.7 thorpej 398: struct iic_softc *sc = device_private(self);
1.1 thorpej 399: struct i2cbus_attach_args *iba = aux;
1.24 martin 400: prop_array_t child_devices;
1.42 jdc 401: prop_dictionary_t props;
1.24 martin 402: char *buf;
1.14 ad 403: i2c_tag_t ic;
404: int rv;
1.42 jdc 405: bool indirect_config;
1.1 thorpej 406:
1.33 jmcneill 407: aprint_naive("\n");
1.1 thorpej 408: aprint_normal(": I2C bus\n");
409:
1.59 ! thorpej 410: sc->sc_dev = self;
1.1 thorpej 411: sc->sc_tag = iba->iba_tag;
1.6 jmcneill 412: sc->sc_type = iba->iba_type;
1.14 ad 413: ic = sc->sc_tag;
1.19 cegger 414: ic->ic_devname = device_xname(self);
1.11 jmcneill 415:
1.13 jmcneill 416: LIST_INIT(&(sc->sc_tag->ic_list));
417: LIST_INIT(&(sc->sc_tag->ic_proc_list));
1.14 ad 418:
1.33 jmcneill 419: rv = kthread_create(PRI_NONE, KTHREAD_MUSTJOIN, NULL,
420: iic_smbus_intr_thread, ic, &ic->ic_intr_thread,
421: "%s", ic->ic_devname);
1.14 ad 422: if (rv)
1.20 xtraeme 423: aprint_error_dev(self, "unable to create intr thread\n");
1.1 thorpej 424:
1.17 jmcneill 425: if (!pmf_device_register(self, NULL, NULL))
426: aprint_error_dev(self, "couldn't establish power handler\n");
427:
1.51 jmcneill 428: if (iba->iba_child_devices) {
429: child_devices = iba->iba_child_devices;
430: indirect_config = false;
431: } else {
432: props = device_properties(parent);
433: if (!prop_dictionary_get_bool(props, "i2c-indirect-config",
434: &indirect_config))
435: indirect_config = true;
436: child_devices = prop_dictionary_get(props, "i2c-child-devices");
437: }
438:
1.24 martin 439: if (child_devices) {
440: unsigned int i, count;
441: prop_dictionary_t dev;
442: prop_data_t cdata;
443: uint32_t addr, size;
444: uint64_t cookie;
445: const char *name;
446: struct i2c_attach_args ia;
1.53 jakllsch 447: int loc[IICCF_NLOCS];
1.24 martin 448:
449: memset(loc, 0, sizeof loc);
450: count = prop_array_count(child_devices);
451: for (i = 0; i < count; i++) {
452: dev = prop_array_get(child_devices, i);
453: if (!dev) continue;
454: if (!prop_dictionary_get_cstring_nocopy(
455: dev, "name", &name))
456: continue;
457: if (!prop_dictionary_get_uint32(dev, "addr", &addr))
458: continue;
459: if (!prop_dictionary_get_uint64(dev, "cookie", &cookie))
460: cookie = 0;
1.53 jakllsch 461: loc[IICCF_ADDR] = addr;
1.24 martin 462: if (prop_dictionary_get_uint32(dev, "size", &size))
1.53 jakllsch 463: loc[IICCF_SIZE] = size;
1.24 martin 464: else
1.54 jakllsch 465: size = loc[IICCF_SIZE] = IICCF_SIZE_DEFAULT;
1.24 martin 466:
467: memset(&ia, 0, sizeof ia);
468: ia.ia_addr = addr;
469: ia.ia_type = sc->sc_type;
470: ia.ia_tag = ic;
471: ia.ia_name = name;
472: ia.ia_cookie = cookie;
1.39 jdc 473: ia.ia_size = size;
1.57 bouyer 474: ia.ia_prop = dev;
1.24 martin 475:
476: buf = NULL;
477: cdata = prop_dictionary_get(dev, "compatible");
478: if (cdata)
479: iic_fill_compat(&ia,
480: prop_data_data_nocopy(cdata),
481: prop_data_size(cdata), &buf);
482:
1.33 jmcneill 483: if (addr > I2C_MAX_ADDR) {
484: aprint_error_dev(self,
485: "WARNING: ignoring bad device address "
486: "@ 0x%02x\n", addr);
487: } else if (sc->sc_devices[addr] == NULL) {
488: sc->sc_devices[addr] =
489: config_found_sm_loc(self, "iic", loc, &ia,
490: iic_print_direct, NULL);
491: }
1.24 martin 492:
493: if (ia.ia_compat)
494: free(ia.ia_compat, M_TEMP);
495: if (buf)
496: free(buf, M_TEMP);
497: }
1.42 jdc 498: } else if (indirect_config) {
1.24 martin 499: /*
500: * Attach all i2c devices described in the kernel
501: * configuration file.
502: */
1.26 jmcneill 503: iic_rescan(self, "iic", NULL);
1.24 martin 504: }
1.1 thorpej 505: }
506:
1.33 jmcneill 507: static int
508: iic_detach(device_t self, int flags)
509: {
510: struct iic_softc *sc = device_private(self);
511: i2c_tag_t ic = sc->sc_tag;
512: int i, error;
513: void *hdl;
514:
515: for (i = 0; i <= I2C_MAX_ADDR; i++) {
516: if (sc->sc_devices[i]) {
517: error = config_detach(sc->sc_devices[i], flags);
518: if (error)
519: return error;
520: }
521: }
522:
523: if (ic->ic_running) {
524: ic->ic_running = 0;
525: wakeup(ic);
526: kthread_join(ic->ic_intr_thread);
527: }
528:
529: if (!LIST_EMPTY(&ic->ic_list)) {
530: device_printf(self, "WARNING: intr handler list not empty\n");
531: while (!LIST_EMPTY(&ic->ic_list)) {
532: hdl = LIST_FIRST(&ic->ic_list);
533: iic_smbus_intr_disestablish(ic, hdl);
534: }
535: }
536: if (!LIST_EMPTY(&ic->ic_proc_list)) {
537: device_printf(self, "WARNING: proc handler list not empty\n");
538: while (!LIST_EMPTY(&ic->ic_proc_list)) {
539: hdl = LIST_FIRST(&ic->ic_proc_list);
540: iic_smbus_intr_disestablish_proc(ic, hdl);
541: }
542: }
543:
544: pmf_device_deregister(self);
545:
546: return 0;
547: }
548:
1.11 jmcneill 549: static void
1.14 ad 550: iic_smbus_intr_thread(void *aux)
1.11 jmcneill 551: {
552: i2c_tag_t ic;
553: struct ic_intr_list *il;
554:
555: ic = (i2c_tag_t)aux;
556: ic->ic_running = 1;
557: ic->ic_pending = 0;
558:
559: while (ic->ic_running) {
560: if (ic->ic_pending == 0)
1.41 martin 561: tsleep(ic, PZERO, "iicintr", hz);
1.11 jmcneill 562: if (ic->ic_pending > 0) {
563: LIST_FOREACH(il, &(ic->ic_proc_list), il_next) {
564: (*il->il_intr)(il->il_intrarg);
565: }
566: ic->ic_pending--;
567: }
568: }
569:
570: kthread_exit(0);
571: }
572:
573: void *
574: iic_smbus_intr_establish(i2c_tag_t ic, int (*intr)(void *), void *intrarg)
575: {
576: struct ic_intr_list *il;
577:
578: il = malloc(sizeof(struct ic_intr_list), M_DEVBUF, M_WAITOK);
579: if (il == NULL)
580: return NULL;
1.28 mbalmer 581:
1.11 jmcneill 582: il->il_intr = intr;
583: il->il_intrarg = intrarg;
584:
585: LIST_INSERT_HEAD(&(ic->ic_list), il, il_next);
586:
587: return il;
588: }
589:
590: void
591: iic_smbus_intr_disestablish(i2c_tag_t ic, void *hdl)
592: {
593: struct ic_intr_list *il;
594:
595: il = (struct ic_intr_list *)hdl;
596:
597: LIST_REMOVE(il, il_next);
598: free(il, M_DEVBUF);
599:
600: return;
601: }
602:
603: void *
604: iic_smbus_intr_establish_proc(i2c_tag_t ic, int (*intr)(void *), void *intrarg)
605: {
606: struct ic_intr_list *il;
607:
608: il = malloc(sizeof(struct ic_intr_list), M_DEVBUF, M_WAITOK);
609: if (il == NULL)
610: return NULL;
1.28 mbalmer 611:
1.11 jmcneill 612: il->il_intr = intr;
613: il->il_intrarg = intrarg;
614:
615: LIST_INSERT_HEAD(&(ic->ic_proc_list), il, il_next);
616:
617: return il;
618: }
619:
620: void
621: iic_smbus_intr_disestablish_proc(i2c_tag_t ic, void *hdl)
622: {
623: struct ic_intr_list *il;
624:
625: il = (struct ic_intr_list *)hdl;
626:
627: LIST_REMOVE(il, il_next);
628: free(il, M_DEVBUF);
629:
630: return;
631: }
632:
633: int
634: iic_smbus_intr(i2c_tag_t ic)
635: {
636: struct ic_intr_list *il;
637:
638: LIST_FOREACH(il, &(ic->ic_list), il_next) {
639: (*il->il_intr)(il->il_intrarg);
640: }
641:
642: ic->ic_pending++;
643: wakeup(ic);
644:
645: return 1;
646: }
647:
1.24 martin 648: static void
649: iic_fill_compat(struct i2c_attach_args *ia, const char *compat, size_t len,
650: char **buffer)
651: {
652: int count, i;
653: const char *c, *start, **ptr;
654:
655: *buffer = NULL;
656: for (i = count = 0, c = compat; i < len; i++, c++)
657: if (*c == 0)
658: count++;
659: count += 2;
660: ptr = malloc(sizeof(char*)*count, M_TEMP, M_WAITOK);
661: if (!ptr) return;
662:
663: for (i = count = 0, start = c = compat; i < len; i++, c++) {
664: if (*c == 0) {
665: ptr[count++] = start;
666: start = c+1;
667: }
668: }
669: if (start < compat+len) {
670: /* last string not 0 terminated */
671: size_t l = c-start;
672: *buffer = malloc(l+1, M_TEMP, M_WAITOK);
673: memcpy(*buffer, start, l);
674: (*buffer)[l] = 0;
675: ptr[count++] = *buffer;
676: }
677: ptr[count] = NULL;
678:
679: ia->ia_compat = ptr;
680: ia->ia_ncompat = count;
681: }
682:
683: int
684: iic_compat_match(struct i2c_attach_args *ia, const char ** compats)
685: {
686: int i;
687:
688: for (; compats && *compats; compats++) {
689: for (i = 0; i < ia->ia_ncompat; i++) {
690: if (strcmp(*compats, ia->ia_compat[i]) == 0)
691: return 1;
692: }
693: }
694: return 0;
695: }
696:
1.31 jmcneill 697: static int
698: iic_open(dev_t dev, int flag, int fmt, lwp_t *l)
699: {
700: struct iic_softc *sc = device_lookup_private(&iic_cd, minor(dev));
701:
1.50 pgoyette 702: mutex_enter(&iic_mtx);
703: if (sc == NULL) {
704: mutex_exit(&iic_mtx);
1.31 jmcneill 705: return ENXIO;
1.50 pgoyette 706: }
707: iic_refcnt++;
708: mutex_exit(&iic_mtx);
1.31 jmcneill 709:
710: return 0;
711: }
712:
713: static int
714: iic_close(dev_t dev, int flag, int fmt, lwp_t *l)
715: {
1.50 pgoyette 716:
717: mutex_enter(&iic_mtx);
718: iic_refcnt--;
719: mutex_exit(&iic_mtx);
720:
1.31 jmcneill 721: return 0;
722: }
723:
724: static int
1.32 jmcneill 725: iic_ioctl_exec(struct iic_softc *sc, i2c_ioctl_exec_t *iie, int flag)
1.31 jmcneill 726: {
727: i2c_tag_t ic = sc->sc_tag;
728: uint8_t buf[I2C_EXEC_MAX_BUFLEN];
1.34 jmcneill 729: void *cmd = NULL;
1.31 jmcneill 730: int error;
731:
732: /* Validate parameters */
733: if (iie->iie_addr > I2C_MAX_ADDR)
734: return EINVAL;
735: if (iie->iie_cmdlen > I2C_EXEC_MAX_CMDLEN ||
736: iie->iie_buflen > I2C_EXEC_MAX_BUFLEN)
737: return EINVAL;
738: if (iie->iie_cmd != NULL && iie->iie_cmdlen == 0)
739: return EINVAL;
740: if (iie->iie_buf != NULL && iie->iie_buflen == 0)
741: return EINVAL;
1.32 jmcneill 742: if (I2C_OP_WRITE_P(iie->iie_op) && (flag & FWRITE) == 0)
743: return EBADF;
1.31 jmcneill 744:
745: #if 0
746: /* Disallow userspace access to devices that have drivers attached. */
747: if (sc->sc_devices[iie->iie_addr] != NULL)
748: return EBUSY;
749: #endif
750:
751: if (iie->iie_cmd != NULL) {
1.34 jmcneill 752: cmd = kmem_alloc(iie->iie_cmdlen, KM_SLEEP);
1.31 jmcneill 753: error = copyin(iie->iie_cmd, cmd, iie->iie_cmdlen);
1.48 christos 754: if (error)
755: goto out;
1.31 jmcneill 756: }
757:
1.46 jakllsch 758: if (iie->iie_buf != NULL && I2C_OP_WRITE_P(iie->iie_op)) {
759: error = copyin(iie->iie_buf, buf, iie->iie_buflen);
1.48 christos 760: if (error)
761: goto out;
1.46 jakllsch 762: }
763:
1.31 jmcneill 764: iic_acquire_bus(ic, 0);
765: error = iic_exec(ic, iie->iie_op, iie->iie_addr, cmd, iie->iie_cmdlen,
766: buf, iie->iie_buflen, 0);
767: iic_release_bus(ic, 0);
768:
1.36 jmcneill 769: /*
770: * Some drivers return error codes on failure, and others return -1.
771: */
772: if (error < 0)
773: error = EIO;
774:
1.48 christos 775: out:
1.34 jmcneill 776: if (cmd)
777: kmem_free(cmd, iie->iie_cmdlen);
778:
1.31 jmcneill 779: if (error)
780: return error;
781:
1.46 jakllsch 782: if (iie->iie_buf != NULL && I2C_OP_READ_P(iie->iie_op))
1.31 jmcneill 783: error = copyout(buf, iie->iie_buf, iie->iie_buflen);
784:
785: return error;
786: }
787:
788: static int
789: iic_ioctl(dev_t dev, u_long cmd, void *data, int flag, lwp_t *l)
790: {
791: struct iic_softc *sc = device_lookup_private(&iic_cd, minor(dev));
792:
793: if (sc == NULL)
794: return ENXIO;
795:
796: switch (cmd) {
797: case I2C_IOCTL_EXEC:
1.32 jmcneill 798: return iic_ioctl_exec(sc, (i2c_ioctl_exec_t *)data, flag);
1.31 jmcneill 799: default:
800: return ENODEV;
801: }
802: }
803:
1.24 martin 804:
1.26 jmcneill 805: CFATTACH_DECL2_NEW(iic, sizeof(struct iic_softc),
1.33 jmcneill 806: iic_match, iic_attach, iic_detach, NULL, iic_rescan, iic_child_detach);
1.28 mbalmer 807:
1.52 pgoyette 808: MODULE(MODULE_CLASS_DRIVER, iic, "i2cexec,i2c_bitbang");
1.28 mbalmer 809:
810: #ifdef _MODULE
811: #include "ioconf.c"
812: #endif
813:
1.50 pgoyette 814: int
815: iic_init(void)
816: {
817:
818: mutex_init(&iic_mtx, MUTEX_DEFAULT, IPL_NONE);
819: iic_refcnt = 0;
820: return 0;
821: }
822:
1.28 mbalmer 823: static int
824: iic_modcmd(modcmd_t cmd, void *opaque)
825: {
1.50 pgoyette 826: #ifdef _MODULE
827: int bmajor, cmajor;
828: #endif
1.28 mbalmer 829: int error;
830:
831: error = 0;
832: switch (cmd) {
833: case MODULE_CMD_INIT:
1.50 pgoyette 834: RUN_ONCE(&iic_once, iic_init);
835:
1.28 mbalmer 836: #ifdef _MODULE
1.50 pgoyette 837: mutex_enter(&iic_mtx);
838: bmajor = cmajor = -1;
839: error = devsw_attach("iic", NULL, &bmajor,
840: &iic_cdevsw, &cmajor);
841: if (error != 0) {
842: mutex_exit(&iic_mtx);
843: break;
844: }
1.28 mbalmer 845: error = config_init_component(cfdriver_ioconf_iic,
846: cfattach_ioconf_iic, cfdata_ioconf_iic);
1.50 pgoyette 847: if (error) {
1.28 mbalmer 848: aprint_error("%s: unable to init component\n",
849: iic_cd.cd_name);
1.50 pgoyette 850: (void)devsw_detach(NULL, &iic_cdevsw);
851: }
852: mutex_exit(&iic_mtx);
1.28 mbalmer 853: #endif
854: break;
855: case MODULE_CMD_FINI:
1.50 pgoyette 856: mutex_enter(&iic_mtx);
857: if (iic_refcnt != 0) {
858: mutex_exit(&iic_mtx);
859: return EBUSY;
860: }
1.28 mbalmer 861: #ifdef _MODULE
1.50 pgoyette 862: error = config_fini_component(cfdriver_ioconf_iic,
1.28 mbalmer 863: cfattach_ioconf_iic, cfdata_ioconf_iic);
1.50 pgoyette 864: if (error != 0) {
865: mutex_exit(&iic_mtx);
866: break;
867: }
868: error = devsw_detach(NULL, &iic_cdevsw);
869: if (error != 0)
870: config_init_component(cfdriver_ioconf_iic,
871: cfattach_ioconf_iic, cfdata_ioconf_iic);
1.28 mbalmer 872: #endif
1.50 pgoyette 873: mutex_exit(&iic_mtx);
1.28 mbalmer 874: break;
875: default:
876: error = ENOTTY;
877: }
878: return error;
879: }
CVSweb <webmaster@jp.NetBSD.org>