[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.44

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

CVSweb <webmaster@jp.NetBSD.org>