[BACK]Return to i2c.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev / i2c

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>