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

1.77.2.6! thorpej     1: /*     $NetBSD: i2c.c,v 1.77.2.5 2021/03/28 20:02:29 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.77.2.6! thorpej    43: __KERNEL_RCSID(0, "$NetBSD: i2c.c,v 1.77.2.5 2021/03/28 20:02:29 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.61      thorpej    70:        device_t sc_dev;
1.1       thorpej    71:        i2c_tag_t sc_tag;
1.27      pgoyette   72:        device_t sc_devices[I2C_MAX_ADDR + 1];
1.1       thorpej    73: };
                     74:
1.31      jmcneill   75: static dev_type_open(iic_open);
                     76: static dev_type_close(iic_close);
                     77: static dev_type_ioctl(iic_ioctl);
                     78:
1.50      pgoyette   79: int iic_init(void);
                     80:
                     81: kmutex_t iic_mtx;
                     82: int iic_refcnt;
                     83:
                     84: ONCE_DECL(iic_once);
                     85:
1.31      jmcneill   86: const struct cdevsw iic_cdevsw = {
1.43      dholland   87:        .d_open = iic_open,
                     88:        .d_close = iic_close,
                     89:        .d_read = noread,
                     90:        .d_write = nowrite,
                     91:        .d_ioctl = iic_ioctl,
                     92:        .d_stop = nostop,
                     93:        .d_tty = notty,
                     94:        .d_poll = nopoll,
                     95:        .d_mmap = nommap,
                     96:        .d_kqfilter = nokqfilter,
1.44      dholland   97:        .d_discard = nodiscard,
1.43      dholland   98:        .d_flag = D_OTHER
1.31      jmcneill   99: };
                    100:
1.11      jmcneill  101: static void    iic_smbus_intr_thread(void *);
1.24      martin    102: static void    iic_fill_compat(struct i2c_attach_args*, const char*,
                    103:                        size_t, char **);
1.11      jmcneill  104:
1.1       thorpej   105: static int
1.24      martin    106: iic_print_direct(void *aux, const char *pnp)
                    107: {
                    108:        struct i2c_attach_args *ia = aux;
                    109:
                    110:        if (pnp != NULL)
1.62      thorpej   111:                aprint_normal("%s at %s addr 0x%02x",
                    112:                              ia->ia_name ? ia->ia_name : "(unknown)",
                    113:                              pnp, ia->ia_addr);
1.24      martin    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.61      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
1.75      thorpej   210: iic_indirect_driver_is_permitted(struct iic_softc *sc, cfdata_t cf)
1.61      thorpej   211: {
                    212:        prop_object_iterator_t iter;
1.75      thorpej   213:        prop_array_t permitlist;
1.61      thorpej   214:        prop_string_t pstr;
                    215:        prop_type_t ptype;
                    216:        bool rv = false;
                    217:
1.75      thorpej   218:        permitlist = prop_dictionary_get(device_properties(sc->sc_dev),
                    219:                                         I2C_PROP_INDIRECT_DEVICE_PERMITLIST);
                    220:        if (permitlist == NULL) {
                    221:                /* No permitlist -> everything allowed */
1.61      thorpej   222:                return (true);
                    223:        }
                    224:
1.75      thorpej   225:        if ((ptype = prop_object_type(permitlist)) != PROP_TYPE_ARRAY) {
1.61      thorpej   226:                aprint_error_dev(sc->sc_dev,
                    227:                    "invalid property type (%d) for '%s'; must be array (%d)\n",
1.75      thorpej   228:                    ptype, I2C_PROP_INDIRECT_DEVICE_PERMITLIST,
                    229:                    PROP_TYPE_ARRAY);
1.61      thorpej   230:                return (false);
                    231:        }
                    232:
1.75      thorpej   233:        iter = prop_array_iterator(permitlist);
1.61      thorpej   234:        while ((pstr = prop_object_iterator_next(iter)) != NULL) {
1.73      thorpej   235:                if (prop_string_equals_string(pstr, cf->cf_name)) {
1.61      thorpej   236:                        rv = true;
                    237:                        break;
                    238:                }
                    239:        }
                    240:        prop_object_iterator_release(iter);
                    241:
                    242:        return (rv);
                    243: }
                    244:
1.1       thorpej   245: static int
1.20      xtraeme   246: iic_search(device_t parent, cfdata_t cf, const int *ldesc, void *aux)
1.1       thorpej   247: {
1.20      xtraeme   248:        struct iic_softc *sc = device_private(parent);
1.1       thorpej   249:        struct i2c_attach_args ia;
1.61      thorpej   250:        int (*probe_func)(struct iic_softc *,
                    251:                          const struct i2c_attach_args *, int);
                    252:        prop_string_t pstr;
                    253:        i2c_addr_t first_addr, last_addr;
1.1       thorpej   254:
1.58      thorpej   255:        /*
1.61      thorpej   256:         * Before we do any more work, consult the allowed-driver
1.75      thorpej   257:         * permit-list for this bus (if any).
1.58      thorpej   258:         */
1.75      thorpej   259:        if (iic_indirect_driver_is_permitted(sc, cf) == false)
1.61      thorpej   260:                return (0);
                    261:
                    262:        /* default to "quick write". */
                    263:        probe_func = iic_probe_smbus_quick_write;
                    264:
                    265:        pstr = prop_dictionary_get(device_properties(sc->sc_dev),
                    266:                                   I2C_PROP_INDIRECT_PROBE_STRATEGY);
                    267:        if (pstr == NULL) {
                    268:                /* Use the default. */
1.73      thorpej   269:        } else if (prop_string_equals_string(pstr,
1.61      thorpej   270:                                        I2C_PROBE_STRATEGY_QUICK_WRITE)) {
                    271:                probe_func = iic_probe_smbus_quick_write;
1.73      thorpej   272:        } else if (prop_string_equals_string(pstr,
1.61      thorpej   273:                                        I2C_PROBE_STRATEGY_RECEIVE_BYTE)) {
                    274:                probe_func = iic_probe_smbus_receive_byte;
1.73      thorpej   275:        } else if (prop_string_equals_string(pstr,
1.61      thorpej   276:                                        I2C_PROBE_STRATEGY_NONE)) {
                    277:                probe_func = iic_probe_none;
                    278:        } else {
                    279:                aprint_error_dev(sc->sc_dev,
                    280:                        "unknown probe strategy '%s'; defaulting to '%s'\n",
1.73      thorpej   281:                        prop_string_value(pstr),
1.61      thorpej   282:                        I2C_PROBE_STRATEGY_QUICK_WRITE);
                    283:
                    284:                /* Use the default. */
                    285:        }
1.58      thorpej   286:
1.1       thorpej   287:        ia.ia_tag = sc->sc_tag;
                    288:
1.25      njoly     289:        ia.ia_name = NULL;
                    290:        ia.ia_ncompat = 0;
                    291:        ia.ia_compat = NULL;
1.57      bouyer    292:        ia.ia_prop = NULL;
1.25      njoly     293:
1.61      thorpej   294:        if (cf->cf_loc[IICCF_ADDR] == IICCF_ADDR_DEFAULT) {
                    295:                /*
                    296:                 * This particular config directive has
                    297:                 * wildcarded the address, so we will
                    298:                 * scan the entire bus for it.
                    299:                 */
                    300:                first_addr = 0;
                    301:                last_addr = I2C_MAX_ADDR;
                    302:        } else {
                    303:                /*
                    304:                 * This config directive hard-wires the i2c
                    305:                 * bus address for the device, so there is
                    306:                 * no need to go poking around at any other
                    307:                 * addresses.
                    308:                 */
                    309:                if (cf->cf_loc[IICCF_ADDR] < 0 ||
                    310:                    cf->cf_loc[IICCF_ADDR] > I2C_MAX_ADDR) {
                    311:                        /* Invalid config directive! */
                    312:                        return (0);
                    313:                }
                    314:                first_addr = last_addr = cf->cf_loc[IICCF_ADDR];
                    315:        }
                    316:
                    317:        for (ia.ia_addr = first_addr; ia.ia_addr <= last_addr; ia.ia_addr++) {
                    318:                int error, match_result;
                    319:
                    320:                /*
                    321:                 * Skip I2C addresses that are reserved for
                    322:                 * special purposes.
                    323:                 */
                    324:                if (iic_is_special_address(ia.ia_addr))
                    325:                        continue;
                    326:
                    327:                /*
                    328:                 * Skip addresses where a device is already attached.
                    329:                 */
1.40      soren     330:                if (sc->sc_devices[ia.ia_addr] != NULL)
                    331:                        continue;
                    332:
1.61      thorpej   333:                /*
                    334:                 * Call the "match" routine for the device.  If that
                    335:                 * returns success, then call the probe strategy
                    336:                 * function.
                    337:                 *
                    338:                 * We do it in this order because i2c devices tend
                    339:                 * to be found at a small number of possible addresses
                    340:                 * (e.g. read-time clocks that are only ever found at
                    341:                 * 0x68).  This gives the driver a chance to skip any
                    342:                 * address that are not valid for the device, saving
                    343:                 * us from having to poke at the bus to see if anything
                    344:                 * is there.
                    345:                 */
                    346:                match_result = config_match(parent, cf, &ia);
                    347:                if (match_result <= 0)
                    348:                        continue;
                    349:
                    350:                /*
                    351:                 * If the quality of the match by the driver was low
                    352:                 * (i.e. matched on being a valid address only, didn't
                    353:                 * perform any hardware probe), invoke our probe routine
                    354:                 * to see if it looks like something is really there.
                    355:                 */
                    356:                if (match_result == I2C_MATCH_ADDRESS_ONLY &&
1.72      thorpej   357:                    (error = (*probe_func)(sc, &ia, 0)) != 0)
1.40      soren     358:                        continue;
                    359:
1.61      thorpej   360:                sc->sc_devices[ia.ia_addr] =
1.77.2.6! thorpej   361:                    config_attach(parent, cf, &ia, iic_print, CFARG_EOL);
1.27      pgoyette  362:        }
1.40      soren     363:
1.30      mbalmer   364:        return 0;
1.1       thorpej   365: }
                    366:
1.27      pgoyette  367: static void
                    368: iic_child_detach(device_t parent, device_t child)
                    369: {
                    370:        struct iic_softc *sc = device_private(parent);
                    371:        int i;
                    372:
                    373:        for (i = 0; i <= I2C_MAX_ADDR; i++)
                    374:                if (sc->sc_devices[i] == child) {
                    375:                        sc->sc_devices[i] = NULL;
                    376:                        break;
1.40      soren     377:                }
1.27      pgoyette  378: }
                    379:
1.1       thorpej   380: static int
1.26      jmcneill  381: iic_rescan(device_t self, const char *ifattr, const int *locators)
                    382: {
1.77.2.1  thorpej   383:        config_search(self, NULL,
                    384:            CFARG_SUBMATCH, iic_search,
1.77.2.2  thorpej   385:            CFARG_LOCATORS, locators,
1.77.2.1  thorpej   386:            CFARG_EOL);
1.26      jmcneill  387:        return 0;
                    388: }
                    389:
                    390: static int
1.20      xtraeme   391: iic_match(device_t parent, cfdata_t cf, void *aux)
1.1       thorpej   392: {
                    393:
1.30      mbalmer   394:        return 1;
1.1       thorpej   395: }
                    396:
                    397: static void
1.20      xtraeme   398: iic_attach(device_t parent, device_t self, void *aux)
1.1       thorpej   399: {
1.7       thorpej   400:        struct iic_softc *sc = device_private(self);
1.1       thorpej   401:        struct i2cbus_attach_args *iba = aux;
1.24      martin    402:        prop_array_t child_devices;
1.42      jdc       403:        prop_dictionary_t props;
1.24      martin    404:        char *buf;
1.14      ad        405:        i2c_tag_t ic;
                    406:        int rv;
1.74      thorpej   407:        bool no_indirect_config = false;
1.1       thorpej   408:
1.33      jmcneill  409:        aprint_naive("\n");
1.1       thorpej   410:        aprint_normal(": I2C bus\n");
                    411:
1.61      thorpej   412:        sc->sc_dev = self;
1.1       thorpej   413:        sc->sc_tag = iba->iba_tag;
1.14      ad        414:        ic = sc->sc_tag;
1.19      cegger    415:        ic->ic_devname = device_xname(self);
1.11      jmcneill  416:
1.13      jmcneill  417:        LIST_INIT(&(sc->sc_tag->ic_list));
                    418:        LIST_INIT(&(sc->sc_tag->ic_proc_list));
1.14      ad        419:
1.33      jmcneill  420:        rv = kthread_create(PRI_NONE, KTHREAD_MUSTJOIN, NULL,
                    421:            iic_smbus_intr_thread, ic, &ic->ic_intr_thread,
                    422:            "%s", ic->ic_devname);
1.14      ad        423:        if (rv)
1.20      xtraeme   424:                aprint_error_dev(self, "unable to create intr thread\n");
1.1       thorpej   425:
1.17      jmcneill  426:        if (!pmf_device_register(self, NULL, NULL))
                    427:                aprint_error_dev(self, "couldn't establish power handler\n");
                    428:
1.51      jmcneill  429:        if (iba->iba_child_devices) {
                    430:                child_devices = iba->iba_child_devices;
1.74      thorpej   431:                no_indirect_config = true;
1.51      jmcneill  432:        } else {
                    433:                props = device_properties(parent);
1.74      thorpej   434:                prop_dictionary_get_bool(props, "i2c-no-indirect-config",
                    435:                    &no_indirect_config);
1.51      jmcneill  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;
1.66      thorpej   443:                uint32_t addr;
1.24      martin    444:                uint64_t cookie;
1.77      jmcneill  445:                uint32_t cookietype;
1.24      martin    446:                const char *name;
                    447:                struct i2c_attach_args ia;
1.53      jakllsch  448:                int loc[IICCF_NLOCS];
1.24      martin    449:
                    450:                memset(loc, 0, sizeof loc);
                    451:                count = prop_array_count(child_devices);
                    452:                for (i = 0; i < count; i++) {
                    453:                        dev = prop_array_get(child_devices, i);
                    454:                        if (!dev) continue;
                    455:                        if (!prop_dictionary_get_cstring_nocopy(
1.62      thorpej   456:                            dev, "name", &name)) {
                    457:                                /* "name" property is optional. */
                    458:                                name = NULL;
                    459:                        }
1.24      martin    460:                        if (!prop_dictionary_get_uint32(dev, "addr", &addr))
                    461:                                continue;
                    462:                        if (!prop_dictionary_get_uint64(dev, "cookie", &cookie))
                    463:                                cookie = 0;
1.77      jmcneill  464:                        if (!prop_dictionary_get_uint32(dev, "cookietype",
                    465:                            &cookietype))
                    466:                                cookietype = I2C_COOKIE_NONE;
1.53      jakllsch  467:                        loc[IICCF_ADDR] = addr;
1.24      martin    468:
                    469:                        memset(&ia, 0, sizeof ia);
                    470:                        ia.ia_addr = addr;
                    471:                        ia.ia_tag = ic;
                    472:                        ia.ia_name = name;
                    473:                        ia.ia_cookie = cookie;
1.77      jmcneill  474:                        ia.ia_cookietype = cookietype;
1.57      bouyer    475:                        ia.ia_prop = dev;
1.24      martin    476:
                    477:                        buf = NULL;
                    478:                        cdata = prop_dictionary_get(dev, "compatible");
                    479:                        if (cdata)
                    480:                                iic_fill_compat(&ia,
1.73      thorpej   481:                                    prop_data_value(cdata),
1.24      martin    482:                                    prop_data_size(cdata), &buf);
                    483:
1.62      thorpej   484:                        if (name == NULL && cdata == NULL) {
1.33      jmcneill  485:                                aprint_error_dev(self,
1.62      thorpej   486:                                    "WARNING: ignoring bad child device entry "
                    487:                                    "for address 0x%02x\n", addr);
                    488:                        } else {
                    489:                                if (addr > I2C_MAX_ADDR) {
                    490:                                        aprint_error_dev(self,
                    491:                                            "WARNING: ignoring bad device "
                    492:                                            "address @ 0x%02x\n", addr);
                    493:                                } else if (sc->sc_devices[addr] == NULL) {
                    494:                                        sc->sc_devices[addr] =
1.77.2.3  thorpej   495:                                            config_found(self, &ia,
                    496:                                            iic_print_direct,
                    497:                                            CFARG_LOCATORS, loc,
                    498:                                            CFARG_EOL);
1.62      thorpej   499:                                }
1.33      jmcneill  500:                        }
1.24      martin    501:
                    502:                        if (ia.ia_compat)
                    503:                                free(ia.ia_compat, M_TEMP);
                    504:                        if (buf)
                    505:                                free(buf, M_TEMP);
                    506:                }
1.74      thorpej   507:        } else if (!no_indirect_config) {
1.24      martin    508:                /*
                    509:                 * Attach all i2c devices described in the kernel
                    510:                 * configuration file.
                    511:                 */
1.26      jmcneill  512:                iic_rescan(self, "iic", NULL);
1.24      martin    513:        }
1.1       thorpej   514: }
                    515:
1.33      jmcneill  516: static int
                    517: iic_detach(device_t self, int flags)
                    518: {
                    519:        struct iic_softc *sc = device_private(self);
                    520:        i2c_tag_t ic = sc->sc_tag;
                    521:        int i, error;
                    522:        void *hdl;
                    523:
                    524:        for (i = 0; i <= I2C_MAX_ADDR; i++) {
                    525:                if (sc->sc_devices[i]) {
                    526:                        error = config_detach(sc->sc_devices[i], flags);
                    527:                        if (error)
                    528:                                return error;
                    529:                }
                    530:        }
                    531:
                    532:        if (ic->ic_running) {
                    533:                ic->ic_running = 0;
                    534:                wakeup(ic);
                    535:                kthread_join(ic->ic_intr_thread);
                    536:        }
                    537:
                    538:        if (!LIST_EMPTY(&ic->ic_list)) {
                    539:                device_printf(self, "WARNING: intr handler list not empty\n");
                    540:                while (!LIST_EMPTY(&ic->ic_list)) {
                    541:                        hdl = LIST_FIRST(&ic->ic_list);
                    542:                        iic_smbus_intr_disestablish(ic, hdl);
                    543:                }
                    544:        }
                    545:        if (!LIST_EMPTY(&ic->ic_proc_list)) {
                    546:                device_printf(self, "WARNING: proc handler list not empty\n");
                    547:                while (!LIST_EMPTY(&ic->ic_proc_list)) {
                    548:                        hdl = LIST_FIRST(&ic->ic_proc_list);
                    549:                        iic_smbus_intr_disestablish_proc(ic, hdl);
                    550:                }
                    551:        }
                    552:
                    553:        pmf_device_deregister(self);
                    554:
                    555:        return 0;
                    556: }
                    557:
1.11      jmcneill  558: static void
1.14      ad        559: iic_smbus_intr_thread(void *aux)
1.11      jmcneill  560: {
                    561:        i2c_tag_t ic;
                    562:        struct ic_intr_list *il;
                    563:
                    564:        ic = (i2c_tag_t)aux;
                    565:        ic->ic_running = 1;
                    566:        ic->ic_pending = 0;
                    567:
                    568:        while (ic->ic_running) {
                    569:                if (ic->ic_pending == 0)
1.41      martin    570:                        tsleep(ic, PZERO, "iicintr", hz);
1.11      jmcneill  571:                if (ic->ic_pending > 0) {
                    572:                        LIST_FOREACH(il, &(ic->ic_proc_list), il_next) {
                    573:                                (*il->il_intr)(il->il_intrarg);
                    574:                        }
                    575:                        ic->ic_pending--;
                    576:                }
                    577:        }
                    578:
                    579:        kthread_exit(0);
                    580: }
                    581:
                    582: void *
                    583: iic_smbus_intr_establish(i2c_tag_t ic, int (*intr)(void *), void *intrarg)
                    584: {
                    585:        struct ic_intr_list *il;
                    586:
                    587:        il = malloc(sizeof(struct ic_intr_list), M_DEVBUF, M_WAITOK);
                    588:        if (il == NULL)
                    589:                return NULL;
1.28      mbalmer   590:
1.11      jmcneill  591:        il->il_intr = intr;
                    592:        il->il_intrarg = intrarg;
                    593:
                    594:        LIST_INSERT_HEAD(&(ic->ic_list), il, il_next);
                    595:
                    596:        return il;
                    597: }
                    598:
                    599: void
                    600: iic_smbus_intr_disestablish(i2c_tag_t ic, void *hdl)
                    601: {
                    602:        struct ic_intr_list *il;
                    603:
                    604:        il = (struct ic_intr_list *)hdl;
                    605:
                    606:        LIST_REMOVE(il, il_next);
                    607:        free(il, M_DEVBUF);
                    608:
                    609:        return;
                    610: }
                    611:
                    612: void *
                    613: iic_smbus_intr_establish_proc(i2c_tag_t ic, int (*intr)(void *), void *intrarg)
                    614: {
                    615:        struct ic_intr_list *il;
                    616:
                    617:        il = malloc(sizeof(struct ic_intr_list), M_DEVBUF, M_WAITOK);
                    618:        if (il == NULL)
                    619:                return NULL;
1.28      mbalmer   620:
1.11      jmcneill  621:        il->il_intr = intr;
                    622:        il->il_intrarg = intrarg;
                    623:
                    624:        LIST_INSERT_HEAD(&(ic->ic_proc_list), il, il_next);
                    625:
                    626:        return il;
                    627: }
                    628:
                    629: void
                    630: iic_smbus_intr_disestablish_proc(i2c_tag_t ic, void *hdl)
                    631: {
                    632:        struct ic_intr_list *il;
                    633:
                    634:        il = (struct ic_intr_list *)hdl;
                    635:
                    636:        LIST_REMOVE(il, il_next);
                    637:        free(il, M_DEVBUF);
                    638:
                    639:        return;
                    640: }
                    641:
                    642: int
                    643: iic_smbus_intr(i2c_tag_t ic)
                    644: {
                    645:        struct ic_intr_list *il;
                    646:
                    647:        LIST_FOREACH(il, &(ic->ic_list), il_next) {
                    648:                (*il->il_intr)(il->il_intrarg);
                    649:        }
                    650:
                    651:        ic->ic_pending++;
                    652:        wakeup(ic);
                    653:
                    654:        return 1;
                    655: }
                    656:
1.24      martin    657: static void
                    658: iic_fill_compat(struct i2c_attach_args *ia, const char *compat, size_t len,
                    659:        char **buffer)
                    660: {
                    661:        int count, i;
                    662:        const char *c, *start, **ptr;
                    663:
                    664:        *buffer = NULL;
                    665:        for (i = count = 0, c = compat; i < len; i++, c++)
                    666:                if (*c == 0)
                    667:                        count++;
                    668:        count += 2;
                    669:        ptr = malloc(sizeof(char*)*count, M_TEMP, M_WAITOK);
                    670:        if (!ptr) return;
                    671:
                    672:        for (i = count = 0, start = c = compat; i < len; i++, c++) {
                    673:                if (*c == 0) {
                    674:                        ptr[count++] = start;
                    675:                        start = c+1;
                    676:                }
                    677:        }
                    678:        if (start < compat+len) {
                    679:                /* last string not 0 terminated */
                    680:                size_t l = c-start;
                    681:                *buffer = malloc(l+1, M_TEMP, M_WAITOK);
                    682:                memcpy(*buffer, start, l);
                    683:                (*buffer)[l] = 0;
                    684:                ptr[count++] = *buffer;
                    685:        }
                    686:        ptr[count] = NULL;
                    687:
                    688:        ia->ia_compat = ptr;
                    689:        ia->ia_ncompat = count;
                    690: }
                    691:
1.62      thorpej   692: /*
1.63      thorpej   693:  * iic_compatible_match --
1.62      thorpej   694:  *     Match a device's "compatible" property against the list
1.63      thorpej   695:  *     of compatible strings provided by the driver.
1.62      thorpej   696:  */
1.65      thorpej   697: int
1.63      thorpej   698: iic_compatible_match(const struct i2c_attach_args *ia,
1.76      thorpej   699:                     const struct device_compatible_entry *compats)
1.63      thorpej   700: {
1.65      thorpej   701:        int match_result;
1.63      thorpej   702:
1.65      thorpej   703:        match_result = device_compatible_match(ia->ia_compat, ia->ia_ncompat,
1.76      thorpej   704:                                               compats);
1.65      thorpej   705:        if (match_result) {
                    706:                match_result =
                    707:                    MIN(I2C_MATCH_DIRECT_COMPATIBLE + match_result - 1,
                    708:                        I2C_MATCH_DIRECT_COMPATIBLE_MAX);
1.63      thorpej   709:        }
1.62      thorpej   710:
1.65      thorpej   711:        return match_result;
1.62      thorpej   712: }
                    713:
1.63      thorpej   714: /*
1.76      thorpej   715:  * iic_compatible_lookup --
                    716:  *     Look the compatible entry that matches one of the driver's
                    717:  *     "compatible" strings.  The first match is returned.
                    718:  */
                    719: const struct device_compatible_entry *
                    720: iic_compatible_lookup(const struct i2c_attach_args *ia,
                    721:                      const struct device_compatible_entry *compats)
                    722: {
                    723:        return device_compatible_lookup(ia->ia_compat, ia->ia_ncompat,
                    724:                                        compats);
                    725: }
                    726:
                    727: /*
1.63      thorpej   728:  * iic_use_direct_match --
                    729:  *     Helper for direct-config of i2c.  Returns true if this is
                    730:  *     a direct-config situation, along with with match result.
                    731:  *     Returns false if the driver should use indirect-config
                    732:  *     matching logic.
                    733:  */
1.62      thorpej   734: bool
                    735: iic_use_direct_match(const struct i2c_attach_args *ia, const cfdata_t cf,
1.63      thorpej   736:                     const struct device_compatible_entry *compats,
                    737:                     int *match_resultp)
1.62      thorpej   738: {
                    739:        KASSERT(match_resultp != NULL);
                    740:
                    741:        if (ia->ia_name != NULL &&
                    742:            strcmp(ia->ia_name, cf->cf_name) == 0) {
                    743:                *match_resultp = I2C_MATCH_DIRECT_SPECIFIC;
                    744:                return true;
                    745:        }
                    746:
                    747:        if (ia->ia_ncompat > 0 && ia->ia_compat != NULL) {
1.76      thorpej   748:                *match_resultp = iic_compatible_match(ia, compats);
1.70      mlelstv   749:                return true;
1.62      thorpej   750:        }
                    751:
                    752:        return false;
1.24      martin    753: }
                    754:
1.31      jmcneill  755: static int
                    756: iic_open(dev_t dev, int flag, int fmt, lwp_t *l)
                    757: {
                    758:        struct iic_softc *sc = device_lookup_private(&iic_cd, minor(dev));
                    759:
1.50      pgoyette  760:        mutex_enter(&iic_mtx);
                    761:        if (sc == NULL) {
                    762:                mutex_exit(&iic_mtx);
1.31      jmcneill  763:                return ENXIO;
1.50      pgoyette  764:        }
                    765:        iic_refcnt++;
                    766:        mutex_exit(&iic_mtx);
1.31      jmcneill  767:
                    768:        return 0;
                    769: }
                    770:
                    771: static int
                    772: iic_close(dev_t dev, int flag, int fmt, lwp_t *l)
                    773: {
1.50      pgoyette  774:
                    775:        mutex_enter(&iic_mtx);
                    776:        iic_refcnt--;
                    777:        mutex_exit(&iic_mtx);
                    778:
1.31      jmcneill  779:        return 0;
                    780: }
                    781:
                    782: static int
1.32      jmcneill  783: iic_ioctl_exec(struct iic_softc *sc, i2c_ioctl_exec_t *iie, int flag)
1.31      jmcneill  784: {
                    785:        i2c_tag_t ic = sc->sc_tag;
                    786:        uint8_t buf[I2C_EXEC_MAX_BUFLEN];
1.34      jmcneill  787:        void *cmd = NULL;
1.31      jmcneill  788:        int error;
                    789:
                    790:        /* Validate parameters */
                    791:        if (iie->iie_addr > I2C_MAX_ADDR)
                    792:                return EINVAL;
                    793:        if (iie->iie_cmdlen > I2C_EXEC_MAX_CMDLEN ||
                    794:            iie->iie_buflen > I2C_EXEC_MAX_BUFLEN)
                    795:                return EINVAL;
                    796:        if (iie->iie_cmd != NULL && iie->iie_cmdlen == 0)
                    797:                return EINVAL;
                    798:        if (iie->iie_buf != NULL && iie->iie_buflen == 0)
                    799:                return EINVAL;
1.32      jmcneill  800:        if (I2C_OP_WRITE_P(iie->iie_op) && (flag & FWRITE) == 0)
                    801:                return EBADF;
1.31      jmcneill  802:
                    803: #if 0
                    804:        /* Disallow userspace access to devices that have drivers attached. */
                    805:        if (sc->sc_devices[iie->iie_addr] != NULL)
                    806:                return EBUSY;
                    807: #endif
                    808:
                    809:        if (iie->iie_cmd != NULL) {
1.34      jmcneill  810:                cmd = kmem_alloc(iie->iie_cmdlen, KM_SLEEP);
1.31      jmcneill  811:                error = copyin(iie->iie_cmd, cmd, iie->iie_cmdlen);
1.48      christos  812:                if (error)
                    813:                        goto out;
1.31      jmcneill  814:        }
                    815:
1.46      jakllsch  816:        if (iie->iie_buf != NULL && I2C_OP_WRITE_P(iie->iie_op)) {
                    817:                error = copyin(iie->iie_buf, buf, iie->iie_buflen);
1.48      christos  818:                if (error)
                    819:                        goto out;
1.46      jakllsch  820:        }
                    821:
1.31      jmcneill  822:        iic_acquire_bus(ic, 0);
                    823:        error = iic_exec(ic, iie->iie_op, iie->iie_addr, cmd, iie->iie_cmdlen,
                    824:            buf, iie->iie_buflen, 0);
                    825:        iic_release_bus(ic, 0);
                    826:
1.36      jmcneill  827:        /*
                    828:         * Some drivers return error codes on failure, and others return -1.
                    829:         */
                    830:        if (error < 0)
                    831:                error = EIO;
                    832:
1.48      christos  833: out:
1.34      jmcneill  834:        if (cmd)
                    835:                kmem_free(cmd, iie->iie_cmdlen);
                    836:
1.31      jmcneill  837:        if (error)
                    838:                return error;
                    839:
1.46      jakllsch  840:        if (iie->iie_buf != NULL && I2C_OP_READ_P(iie->iie_op))
1.31      jmcneill  841:                error = copyout(buf, iie->iie_buf, iie->iie_buflen);
                    842:
                    843:        return error;
                    844: }
                    845:
                    846: static int
                    847: iic_ioctl(dev_t dev, u_long cmd, void *data, int flag, lwp_t *l)
                    848: {
                    849:        struct iic_softc *sc = device_lookup_private(&iic_cd, minor(dev));
                    850:
                    851:        if (sc == NULL)
                    852:                return ENXIO;
                    853:
                    854:        switch (cmd) {
                    855:        case I2C_IOCTL_EXEC:
1.32      jmcneill  856:                return iic_ioctl_exec(sc, (i2c_ioctl_exec_t *)data, flag);
1.31      jmcneill  857:        default:
                    858:                return ENODEV;
                    859:        }
                    860: }
                    861:
1.24      martin    862:
1.67      jdolecek  863: CFATTACH_DECL3_NEW(iic, sizeof(struct iic_softc),
                    864:     iic_match, iic_attach, iic_detach, NULL, iic_rescan, iic_child_detach,
                    865:     DVF_DETACH_SHUTDOWN);
1.28      mbalmer   866:
1.52      pgoyette  867: MODULE(MODULE_CLASS_DRIVER, iic, "i2cexec,i2c_bitbang");
1.28      mbalmer   868:
                    869: #ifdef _MODULE
                    870: #include "ioconf.c"
                    871: #endif
                    872:
1.50      pgoyette  873: int
                    874: iic_init(void)
                    875: {
                    876:
                    877:        mutex_init(&iic_mtx, MUTEX_DEFAULT, IPL_NONE);
                    878:        iic_refcnt = 0;
                    879:        return 0;
                    880: }
                    881:
1.28      mbalmer   882: static int
                    883: iic_modcmd(modcmd_t cmd, void *opaque)
                    884: {
1.50      pgoyette  885: #ifdef _MODULE
                    886:        int bmajor, cmajor;
                    887: #endif
1.28      mbalmer   888:        int error;
                    889:
                    890:        error = 0;
                    891:        switch (cmd) {
                    892:        case MODULE_CMD_INIT:
1.50      pgoyette  893:                RUN_ONCE(&iic_once, iic_init);
                    894:
1.28      mbalmer   895: #ifdef _MODULE
1.50      pgoyette  896:                mutex_enter(&iic_mtx);
                    897:                bmajor = cmajor = -1;
                    898:                error = devsw_attach("iic", NULL, &bmajor,
                    899:                    &iic_cdevsw, &cmajor);
                    900:                if (error != 0) {
                    901:                        mutex_exit(&iic_mtx);
                    902:                        break;
                    903:                }
1.28      mbalmer   904:                error = config_init_component(cfdriver_ioconf_iic,
                    905:                    cfattach_ioconf_iic, cfdata_ioconf_iic);
1.50      pgoyette  906:                if (error) {
1.28      mbalmer   907:                        aprint_error("%s: unable to init component\n",
                    908:                            iic_cd.cd_name);
1.50      pgoyette  909:                        (void)devsw_detach(NULL, &iic_cdevsw);
                    910:                }
                    911:                mutex_exit(&iic_mtx);
1.28      mbalmer   912: #endif
                    913:                break;
                    914:        case MODULE_CMD_FINI:
1.50      pgoyette  915:                mutex_enter(&iic_mtx);
                    916:                if (iic_refcnt != 0) {
                    917:                        mutex_exit(&iic_mtx);
                    918:                        return EBUSY;
                    919:                }
1.28      mbalmer   920: #ifdef _MODULE
1.50      pgoyette  921:                error = config_fini_component(cfdriver_ioconf_iic,
1.28      mbalmer   922:                    cfattach_ioconf_iic, cfdata_ioconf_iic);
1.50      pgoyette  923:                if (error != 0) {
                    924:                        mutex_exit(&iic_mtx);
                    925:                        break;
                    926:                }
                    927:                error = devsw_detach(NULL, &iic_cdevsw);
                    928:                if (error != 0)
                    929:                        config_init_component(cfdriver_ioconf_iic,
                    930:                            cfattach_ioconf_iic, cfdata_ioconf_iic);
1.28      mbalmer   931: #endif
1.50      pgoyette  932:                mutex_exit(&iic_mtx);
1.28      mbalmer   933:                break;
                    934:        default:
                    935:                error = ENOTTY;
                    936:        }
                    937:        return error;
                    938: }

CVSweb <webmaster@jp.NetBSD.org>