[BACK]Return to kiic.c CVS log [TXT][DIR] Up to [local] / sys / arch / macppc / dev

Annotation of sys/arch/macppc/dev/kiic.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: kiic.c,v 1.2 2007/05/20 23:38:52 thib Exp $   */
                      2: /*     $NetBSD: kiic.c,v 1.1 2003/12/27 02:19:34 grant Exp $   */
                      3:
                      4: /*-
                      5:  * Copyright (c) 2001 Tsubai Masanari.  All rights reserved.
                      6:  *
                      7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions
                      9:  * are met:
                     10:  * 1. Redistributions of source code must retain the above copyright
                     11:  *    notice, this list of conditions and the following disclaimer.
                     12:  * 2. Redistributions in binary form must reproduce the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer in the
                     14:  *    documentation and/or other materials provided with the distribution.
                     15:  * 3. The name of the author may not be used to endorse or promote products
                     16:  *    derived from this software without specific prior written permission.
                     17:  *
                     18:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
                     19:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
                     20:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
                     21:  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
                     22:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
                     23:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
                     24:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
                     25:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
                     26:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
                     27:  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     28:  */
                     29:
                     30: #include <sys/param.h>
                     31: #include <sys/device.h>
                     32: #include <sys/systm.h>
                     33:
                     34: #include <dev/ofw/openfirm.h>
                     35: #include <uvm/uvm_extern.h>
                     36: #include <machine/autoconf.h>
                     37:
                     38: #include <macppc/dev/kiicvar.h>
                     39: #include <macppc/dev/maci2cvar.h>
                     40:
                     41: int kiic_match(struct device *, void *, void *);
                     42: void kiic_attach(struct device *, struct device *, void *);
                     43: void kiic_attach_bus(struct kiic_softc *, struct kiic_bus *, int);
                     44: inline u_int kiic_readreg(struct kiic_softc *, int);
                     45: inline void kiic_writereg(struct kiic_softc *, int, u_int);
                     46: u_int kiic_getmode(struct kiic_softc *);
                     47: void kiic_setmode(struct kiic_softc *, u_int, u_int);
                     48: u_int kiic_getspeed(struct kiic_softc *);
                     49: void kiic_setspeed(struct kiic_softc *, u_int);
                     50: int kiic_intr(struct kiic_softc *);
                     51: int kiic_poll(struct kiic_softc *, int);
                     52: int kiic_start(struct kiic_softc *, int, int, void *, int);
                     53: int kiic_read(struct kiic_softc *, int, int, void *, int);
                     54: int kiic_write(struct kiic_softc *, int, int, const void *, int);
                     55:
                     56: /* I2C glue */
                     57: int kiic_i2c_acquire_bus(void *, int);
                     58: void kiic_i2c_release_bus(void *, int);
                     59: int kiic_i2c_exec(void *, i2c_op_t, i2c_addr_t, const void *, size_t,
                     60:     void *, size_t, int);
                     61:
                     62: struct cfattach kiic_ca = {
                     63:        sizeof(struct kiic_softc), kiic_match, kiic_attach
                     64: };
                     65: struct cfattach kiic_memc_ca = {
                     66:        sizeof(struct kiic_softc), kiic_match, kiic_attach
                     67: };
                     68:
                     69: struct cfdriver kiic_cd = {
                     70:        NULL, "kiic", DV_DULL
                     71: };
                     72:
                     73: int
                     74: kiic_match(struct device *parent, void *match, void *aux)
                     75: {
                     76:        struct confargs *ca = aux;
                     77:
                     78:        if (strcmp(ca->ca_name, "i2c") == 0 &&
                     79:           ca->ca_nreg >= 4)
                     80:                return (1);
                     81:
                     82:        return (0);
                     83: }
                     84:
                     85: void
                     86: kiic_attach(struct device *parent, struct device *self, void *aux)
                     87: {
                     88:        struct kiic_softc *sc = (struct kiic_softc *)self;
                     89:        struct confargs *ca = aux;
                     90:        int node = ca->ca_node;
                     91:        int rate, count = 0;
                     92:        char name[32];
                     93:
                     94:        ca->ca_reg[0] += ca->ca_baseaddr;
                     95:
                     96:        if (OF_getprop(node, "AAPL,i2c-rate", &rate, 4) != 4) {
                     97:                printf(": cannot get i2c-rate\n");
                     98:                return;
                     99:        }
                    100:        if (OF_getprop(node, "AAPL,address", &sc->sc_paddr, 4) != 4) {
                    101:                printf(": unable to find i2c address\n");
                    102:                return;
                    103:        }
                    104:        if (OF_getprop(node, "AAPL,address-step", &sc->sc_regstep, 4) != 4) {
                    105:                printf(": unable to find i2c address step\n");
                    106:                return;
                    107:        }
                    108:        sc->sc_reg = mapiodev(sc->sc_paddr, (DATA+1)*sc->sc_regstep);
                    109:
                    110:        printf("\n");
                    111:
                    112:        kiic_writereg(sc, STATUS, 0);
                    113:        kiic_writereg(sc, ISR, 0);
                    114:        kiic_writereg(sc, IER, 0);
                    115:
                    116:        kiic_setmode(sc, I2C_STDSUBMODE, 0);
                    117:        kiic_setspeed(sc, I2C_100kHz);          /* XXX rate */
                    118:
                    119:        rw_init(&sc->sc_buslock, sc->sc_dev.dv_xname);
                    120:        kiic_writereg(sc, IER,I2C_INT_DATA|I2C_INT_ADDR|I2C_INT_STOP);
                    121:
                    122:        for (node = OF_child(ca->ca_node); node; node = OF_peer(node)) {
                    123:                if (OF_getprop(node, "name", &name, sizeof name) > 0) {
                    124:                        if (strcmp(name, "i2c-bus") == 0) {
                    125:                                kiic_attach_bus(sc, &sc->sc_bus[count], node);
                    126:                                if (++count >= KIIC_MAX_BUSSES)
                    127:                                        break;
                    128:                        }
                    129:                }
                    130:        }
                    131:
                    132:        /*
                    133:         * If we didn't find any i2c-bus nodes, there is only a single
                    134:         * i2c bus.
                    135:         */
                    136:
                    137:        if (count == 0)
                    138:                kiic_attach_bus(sc, &sc->sc_bus[0], ca->ca_node);
                    139: }
                    140:
                    141: void
                    142: kiic_attach_bus(struct kiic_softc *sc, struct kiic_bus *bus, int node)
                    143: {
                    144:        struct i2cbus_attach_args iba;
                    145:        u_int32_t reg;
                    146:
                    147:        if (OF_getprop(node, "reg", &reg, sizeof reg) != sizeof reg)
                    148:                return;
                    149:
                    150:        bus->sc = sc;
                    151:        bus->i2c_tag.ic_cookie = bus;
                    152:        bus->i2c_tag.ic_acquire_bus = kiic_i2c_acquire_bus;
                    153:        bus->i2c_tag.ic_release_bus = kiic_i2c_release_bus;
                    154:        bus->i2c_tag.ic_exec = kiic_i2c_exec;
                    155:        bus->reg = reg;
                    156:
                    157:        bzero(&iba, sizeof iba);
                    158:        iba.iba_name = "iic";
                    159:        iba.iba_tag = &bus->i2c_tag;
                    160:        iba.iba_bus_scan = maciic_scan;
                    161:        iba.iba_bus_scan_arg = &node;
                    162:        config_found(&sc->sc_dev, &iba, NULL);
                    163: }
                    164:
                    165: u_int
                    166: kiic_readreg(struct kiic_softc *sc, int reg)
                    167: {
                    168:        u_char *addr = sc->sc_reg + sc->sc_regstep * reg;
                    169:
                    170:        return (*addr);
                    171: }
                    172:
                    173: void
                    174: kiic_writereg(struct kiic_softc *sc, int reg, u_int val)
                    175: {
                    176:        u_char *addr = sc->sc_reg + sc->sc_regstep * reg;
                    177:
                    178:        *addr = val;
                    179:        asm volatile ("eieio");
                    180:        delay(10);
                    181: }
                    182:
                    183: u_int
                    184: kiic_getmode(struct kiic_softc *sc)
                    185: {
                    186:        return kiic_readreg(sc, MODE) & I2C_MODE;
                    187: }
                    188:
                    189: void
                    190: kiic_setmode(struct kiic_softc *sc, u_int mode, u_int bus)
                    191: {
                    192:        u_int x;
                    193:
                    194:        KASSERT((mode & ~I2C_MODE) == 0);
                    195:        x = kiic_readreg(sc, MODE);
                    196:        x &= ~(I2C_MODE);
                    197:        if (bus)
                    198:                x |= I2C_BUS1;
                    199:        else
                    200:                x &= ~I2C_BUS1;
                    201:        x |= mode;
                    202:        kiic_writereg(sc, MODE, x);
                    203: }
                    204:
                    205: u_int
                    206: kiic_getspeed(struct kiic_softc *sc)
                    207: {
                    208:        return kiic_readreg(sc, MODE) & I2C_SPEED;
                    209: }
                    210:
                    211: void
                    212: kiic_setspeed(struct kiic_softc *sc, u_int speed)
                    213: {
                    214:        u_int x;
                    215:
                    216:        KASSERT((speed & ~I2C_SPEED) == 0);
                    217:        x = kiic_readreg(sc, MODE);
                    218:        x &= ~I2C_SPEED;
                    219:        x |= speed;
                    220:        kiic_writereg(sc, MODE, x);
                    221: }
                    222:
                    223: int
                    224: kiic_intr(struct kiic_softc *sc)
                    225: {
                    226:        u_int isr, x;
                    227:
                    228:        isr = kiic_readreg(sc, ISR);
                    229:        if (isr & I2C_INT_ADDR) {
                    230: #if 0
                    231:                if ((kiic_readreg(sc, STATUS) & I2C_ST_LASTAAK) == 0) {
                    232:                        /* No slave responded. */
                    233:                        sc->sc_flags |= I2C_ERROR;
                    234:                        goto out;
                    235:                }
                    236: #endif
                    237:
                    238:                if (sc->sc_flags & I2C_READING) {
                    239:                        if (sc->sc_resid > 1) {
                    240:                                x = kiic_readreg(sc, CONTROL);
                    241:                                x |= I2C_CT_AAK;
                    242:                                kiic_writereg(sc, CONTROL, x);
                    243:                        }
                    244:                } else {
                    245:                        kiic_writereg(sc, DATA, *sc->sc_data++);
                    246:                        sc->sc_resid--;
                    247:                }
                    248:        }
                    249:
                    250:        if (isr & I2C_INT_DATA) {
                    251:                if (sc->sc_flags & I2C_READING) {
                    252:                        *sc->sc_data++ = kiic_readreg(sc, DATA);
                    253:                        sc->sc_resid--;
                    254:
                    255:                        if (sc->sc_resid == 0) {        /* Completed */
                    256:                                kiic_writereg(sc, CONTROL, 0);
                    257:                                goto out;
                    258:                        }
                    259:                } else {
                    260: #if 0
                    261:                        if ((kiic_readreg(sc, STATUS) & I2C_ST_LASTAAK) == 0) {
                    262:                                /* No slave responded. */
                    263:                                sc->sc_flags |= I2C_ERROR;
                    264:                                goto out;
                    265:                        }
                    266: #endif
                    267:
                    268:                        if (sc->sc_resid == 0) {
                    269:                                x = kiic_readreg(sc, CONTROL) | I2C_CT_STOP;
                    270:                                kiic_writereg(sc, CONTROL, x);
                    271:                        } else {
                    272:                                kiic_writereg(sc, DATA, *sc->sc_data++);
                    273:                                sc->sc_resid--;
                    274:                        }
                    275:                }
                    276:        }
                    277:
                    278: out:
                    279:        if (isr & I2C_INT_STOP) {
                    280:                kiic_writereg(sc, CONTROL, 0);
                    281:                sc->sc_flags &= ~I2C_BUSY;
                    282:        }
                    283:
                    284:        kiic_writereg(sc, ISR, isr);
                    285:
                    286:        return (1);
                    287: }
                    288:
                    289: int
                    290: kiic_poll(struct kiic_softc *sc, int timo)
                    291: {
                    292:        while (sc->sc_flags & I2C_BUSY) {
                    293:                if (kiic_readreg(sc, ISR))
                    294:                        kiic_intr(sc);
                    295:                timo -= 100;
                    296:                if (timo < 0) {
                    297:                        printf("i2c_poll: timeout\n");
                    298:                        return (-1);
                    299:                }
                    300:                delay(100);
                    301:        }
                    302:        return (0);
                    303: }
                    304:
                    305: int
                    306: kiic_start(struct kiic_softc *sc, int addr, int subaddr, void *data, int len)
                    307: {
                    308:        int rw = (sc->sc_flags & I2C_READING) ? 1 : 0;
                    309:        int timo, x;
                    310:
                    311:        KASSERT((addr & 1) == 0);
                    312:
                    313:        sc->sc_data = data;
                    314:        sc->sc_resid = len;
                    315:        sc->sc_flags |= I2C_BUSY;
                    316:
                    317:        timo = 1000 + len * 200;
                    318:
                    319:        /* XXX TAS3001 sometimes takes 50ms to finish writing registers. */
                    320:        /* if (addr == 0x68) */
                    321:                timo += 100000;
                    322:
                    323:        kiic_writereg(sc, ADDR, addr | rw);
                    324:        kiic_writereg(sc, SUBADDR, subaddr);
                    325:
                    326:        x = kiic_readreg(sc, CONTROL) | I2C_CT_ADDR;
                    327:        kiic_writereg(sc, CONTROL, x);
                    328:
                    329:        if (kiic_poll(sc, timo))
                    330:                return (-1);
                    331:        if (sc->sc_flags & I2C_ERROR) {
                    332:                printf("I2C_ERROR\n");
                    333:                return (-1);
                    334:        }
                    335:        return (0);
                    336: }
                    337:
                    338: int
                    339: kiic_read(struct kiic_softc *sc, int addr, int subaddr, void *data, int len)
                    340: {
                    341:        sc->sc_flags = I2C_READING;
                    342:        return kiic_start(sc, addr, subaddr, data, len);
                    343: }
                    344:
                    345: int
                    346: kiic_write(struct kiic_softc *sc, int addr, int subaddr, const void *data, int len)
                    347: {
                    348:        sc->sc_flags = 0;
                    349:        return kiic_start(sc, addr, subaddr, (void *)data, len);
                    350: }
                    351:
                    352: int
                    353: kiic_i2c_acquire_bus(void *cookie, int flags)
                    354: {
                    355:        struct kiic_bus *bus = cookie;
                    356:
                    357:        return (rw_enter(&bus->sc->sc_buslock, RW_WRITE));
                    358: }
                    359:
                    360: void
                    361: kiic_i2c_release_bus(void *cookie, int flags)
                    362: {
                    363:        struct kiic_bus *bus = cookie;
                    364:
                    365:        (void) rw_exit(&bus->sc->sc_buslock);
                    366: }
                    367:
                    368: int
                    369: kiic_i2c_exec(void *cookie, i2c_op_t op, i2c_addr_t addr,
                    370:     const void *cmdbuf, size_t cmdlen, void *buf, size_t len, int flags)
                    371: {
                    372:        struct kiic_bus *bus = cookie;
                    373:        u_int mode = I2C_STDSUBMODE;
                    374:        u_int8_t cmd = 0;
                    375:
                    376:        if (!I2C_OP_STOP_P(op) || cmdlen > 1)
                    377:                return (EINVAL);
                    378:
                    379:        if (cmdlen == 0)
                    380:                mode = I2C_STDMODE;
                    381:        else if (I2C_OP_READ_P(op))
                    382:                mode = I2C_COMBMODE;
                    383:
                    384:        if (cmdlen > 0)
                    385:                cmd = *(u_int8_t *)cmdbuf;
                    386:
                    387:        kiic_setmode(bus->sc, mode, bus->reg || addr & 0x80);
                    388:        addr &= 0x7f;
                    389:
                    390:        if (I2C_OP_READ_P(op)) {
                    391:                if (kiic_read(bus->sc, (addr << 1), cmd, buf, len) != 0)
                    392:                        return (EIO);
                    393:        } else {
                    394:                if (kiic_write(bus->sc, (addr << 1), cmd, buf, len) != 0)
                    395:                        return (EIO);
                    396:        }
                    397:        return (0);
                    398: }

CVSweb