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

1.14.6.1! jmcneill    1: /*     $NetBSD: i2c.c,v 1.15 2007/09/01 22:19:25 riz 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:
                     38: #include <sys/param.h>
                     39: #include <sys/systm.h>
                     40: #include <sys/device.h>
                     41: #include <sys/event.h>
                     42: #include <sys/conf.h>
1.11      jmcneill   43: #include <sys/malloc.h>
                     44: #include <sys/kthread.h>
                     45: #include <sys/proc.h>
                     46: #include <sys/kernel.h>
1.1       thorpej    47:
                     48: #include <dev/i2c/i2cvar.h>
                     49:
                     50: #include "locators.h"
                     51:
                     52: struct iic_softc {
                     53:        struct device sc_dev;
                     54:        i2c_tag_t sc_tag;
1.6       jmcneill   55:        int sc_type;
1.1       thorpej    56: };
                     57:
1.11      jmcneill   58: static void    iic_smbus_intr_thread(void *);
                     59:
1.1       thorpej    60: int
1.10      christos   61: iicbus_print(void *aux, const char *pnp)
1.1       thorpej    62: {
                     63:
                     64:        if (pnp != NULL)
1.8       drochner   65:                aprint_normal("iic at %s", pnp);
1.1       thorpej    66:
                     67:        return (UNCONF);
                     68: }
                     69:
                     70: static int
1.10      christos   71: iic_print(void *aux, const char *pnp)
1.1       thorpej    72: {
                     73:        struct i2c_attach_args *ia = aux;
                     74:
1.6       jmcneill   75:        if (ia->ia_addr != (i2c_addr_t)-1)
                     76:                aprint_normal(" addr 0x%x", ia->ia_addr);
1.1       thorpej    77:
                     78:        return (UNCONF);
                     79: }
                     80:
                     81: static int
1.3       drochner   82: iic_search(struct device *parent, struct cfdata *cf,
1.10      christos   83:     const int *ldesc, void *aux)
1.1       thorpej    84: {
                     85:        struct iic_softc *sc = (void *) parent;
                     86:        struct i2c_attach_args ia;
                     87:
                     88:        ia.ia_tag = sc->sc_tag;
                     89:        ia.ia_addr = cf->cf_loc[IICCF_ADDR];
                     90:        ia.ia_size = cf->cf_loc[IICCF_SIZE];
1.6       jmcneill   91:        ia.ia_type = sc->sc_type;
1.1       thorpej    92:
                     93:        if (config_match(parent, cf, &ia) > 0)
                     94:                config_attach(parent, cf, &ia, iic_print);
                     95:
                     96:        return (0);
                     97: }
                     98:
                     99: static int
1.10      christos  100: iic_match(struct device *parent, struct cfdata *cf,
                    101:     void *aux)
1.1       thorpej   102: {
                    103:
1.8       drochner  104:        return (1);
1.1       thorpej   105: }
                    106:
                    107: static void
1.10      christos  108: iic_attach(struct device *parent, struct device *self, void *aux)
1.1       thorpej   109: {
1.7       thorpej   110:        struct iic_softc *sc = device_private(self);
1.1       thorpej   111:        struct i2cbus_attach_args *iba = aux;
1.14.6.1! jmcneill  112:        i2c_addr_t addr;
1.14      ad        113:        i2c_tag_t ic;
                    114:        int rv;
1.14.6.1! jmcneill  115:        int found = 0;
        !           116:        uint8_t cmd = 0, val;
1.1       thorpej   117:
                    118:        aprint_naive(": I2C bus\n");
                    119:        aprint_normal(": I2C bus\n");
                    120:
                    121:        sc->sc_tag = iba->iba_tag;
1.6       jmcneill  122:        sc->sc_type = iba->iba_type;
1.14      ad        123:        ic = sc->sc_tag;
                    124:        ic->ic_devname = self->dv_xname;
1.11      jmcneill  125:
1.13      jmcneill  126:        LIST_INIT(&(sc->sc_tag->ic_list));
                    127:        LIST_INIT(&(sc->sc_tag->ic_proc_list));
1.14      ad        128:
                    129:        rv = kthread_create(PRI_NONE, 0, NULL, iic_smbus_intr_thread,
                    130:            ic, &ic->ic_intr_thread, "%s", ic->ic_devname);
                    131:        if (rv)
                    132:                printf("%s: unable to create intr thread\n", ic->ic_devname);
1.1       thorpej   133:
1.14.6.1! jmcneill  134:        if (sc->sc_type == I2C_TYPE_SMBUS) {
        !           135:                for (addr = 0x0; addr < 0x80; addr++) {
        !           136:                        iic_acquire_bus(ic, 0);
        !           137:                        if (iic_exec(ic, I2C_OP_READ_WITH_STOP, addr,
        !           138:                            &cmd, 1, &val, 1, 0) == 0) {
        !           139:                                if (found == 0)
        !           140:                                        aprint_normal("%s: devices at",
        !           141:                                                        ic->ic_devname);
        !           142:                                found++;
        !           143:                                aprint_normal(" 0x%02x", addr);
        !           144:                        }
        !           145:                        iic_release_bus(ic, 0);
        !           146:                }
        !           147:                if (found == 0)
        !           148:                        aprint_normal("%s: no devices found", ic->ic_devname);
        !           149:                aprint_normal("\n");
        !           150:        }
        !           151:
1.1       thorpej   152:        /*
1.2       wiz       153:         * Attach all i2c devices described in the kernel
1.1       thorpej   154:         * configuration file.
                    155:         */
1.3       drochner  156:        config_search_ia(iic_search, self, "iic", NULL);
1.1       thorpej   157: }
                    158:
1.11      jmcneill  159: static void
1.14      ad        160: iic_smbus_intr_thread(void *aux)
1.11      jmcneill  161: {
                    162:        i2c_tag_t ic;
                    163:        struct ic_intr_list *il;
                    164:        int rv;
                    165:
                    166:        ic = (i2c_tag_t)aux;
                    167:        ic->ic_running = 1;
                    168:        ic->ic_pending = 0;
                    169:
                    170:        while (ic->ic_running) {
                    171:                if (ic->ic_pending == 0)
                    172:                        rv = tsleep(ic, PZERO, "iicintr", hz);
                    173:                if (ic->ic_pending > 0) {
                    174:                        LIST_FOREACH(il, &(ic->ic_proc_list), il_next) {
                    175:                                (*il->il_intr)(il->il_intrarg);
                    176:                        }
                    177:                        ic->ic_pending--;
                    178:                }
                    179:        }
                    180:
                    181:        kthread_exit(0);
                    182: }
                    183:
                    184: void *
                    185: iic_smbus_intr_establish(i2c_tag_t ic, int (*intr)(void *), void *intrarg)
                    186: {
                    187:        struct ic_intr_list *il;
                    188:
                    189:        il = malloc(sizeof(struct ic_intr_list), M_DEVBUF, M_WAITOK);
                    190:        if (il == NULL)
                    191:                return NULL;
                    192:
                    193:        il->il_intr = intr;
                    194:        il->il_intrarg = intrarg;
                    195:
                    196:        LIST_INSERT_HEAD(&(ic->ic_list), il, il_next);
                    197:
                    198:        return il;
                    199: }
                    200:
                    201: void
                    202: iic_smbus_intr_disestablish(i2c_tag_t ic, void *hdl)
                    203: {
                    204:        struct ic_intr_list *il;
                    205:
                    206:        il = (struct ic_intr_list *)hdl;
                    207:
                    208:        LIST_REMOVE(il, il_next);
                    209:        free(il, M_DEVBUF);
                    210:
                    211:        return;
                    212: }
                    213:
                    214: void *
                    215: iic_smbus_intr_establish_proc(i2c_tag_t ic, int (*intr)(void *), void *intrarg)
                    216: {
                    217:        struct ic_intr_list *il;
                    218:
                    219:        il = malloc(sizeof(struct ic_intr_list), M_DEVBUF, M_WAITOK);
                    220:        if (il == NULL)
                    221:                return NULL;
                    222:
                    223:        il->il_intr = intr;
                    224:        il->il_intrarg = intrarg;
                    225:
                    226:        LIST_INSERT_HEAD(&(ic->ic_proc_list), il, il_next);
                    227:
                    228:        return il;
                    229: }
                    230:
                    231: void
                    232: iic_smbus_intr_disestablish_proc(i2c_tag_t ic, void *hdl)
                    233: {
                    234:        struct ic_intr_list *il;
                    235:
                    236:        il = (struct ic_intr_list *)hdl;
                    237:
                    238:        LIST_REMOVE(il, il_next);
                    239:        free(il, M_DEVBUF);
                    240:
                    241:        return;
                    242: }
                    243:
                    244: int
                    245: iic_smbus_intr(i2c_tag_t ic)
                    246: {
                    247:        struct ic_intr_list *il;
                    248:
                    249:        LIST_FOREACH(il, &(ic->ic_list), il_next) {
                    250:                (*il->il_intr)(il->il_intrarg);
                    251:        }
                    252:
                    253:        ic->ic_pending++;
                    254:        wakeup(ic);
                    255:
                    256:        return 1;
                    257: }
                    258:
1.1       thorpej   259: CFATTACH_DECL(iic, sizeof(struct iic_softc),
                    260:     iic_match, iic_attach, NULL, NULL);

CVSweb <webmaster@jp.NetBSD.org>