[BACK]Return to iopi2c.c CVS log [TXT][DIR] Up to [local] / sys / arch / arm / xscale

Annotation of sys/arch/arm/xscale/iopi2c.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: iopi2c.c,v 1.2 2006/07/10 15:39:56 drahn Exp $        */
                      2: /*     $NetBSD: iopi2c.c,v 1.3 2005/12/11 12:16:51 christos Exp $      */
                      3:
                      4: /*
                      5:  * Copyright (c) 2003 Wasabi Systems, Inc.
                      6:  * All rights reserved.
                      7:  *
                      8:  * Written by Jason R. Thorpe for Wasabi Systems, Inc.
                      9:  *
                     10:  * Redistribution and use in source and binary forms, with or without
                     11:  * modification, are permitted provided that the following conditions
                     12:  * are met:
                     13:  * 1. Redistributions of source code must retain the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer.
                     15:  * 2. Redistributions in binary form must reproduce the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer in the
                     17:  *    documentation and/or other materials provided with the distribution.
                     18:  * 3. All advertising materials mentioning features or use of this software
                     19:  *    must display the following acknowledgement:
                     20:  *     This product includes software developed for the NetBSD Project by
                     21:  *     Wasabi Systems, Inc.
                     22:  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
                     23:  *    or promote products derived from this software without specific prior
                     24:  *    written permission.
                     25:  *
                     26:  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
                     27:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     28:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     29:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
                     30:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     31:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     32:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     33:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     34:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     35:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     36:  * POSSIBILITY OF SUCH DAMAGE.
                     37:  */
                     38:
                     39: /*
                     40:  * Intel i80321 I/O Processor I2C Controller Unit support.
                     41:  */
                     42: #include <sys/param.h>
                     43: #include <sys/lock.h>
                     44: #include <sys/systm.h>
                     45: #include <sys/device.h>
                     46: #include <sys/kernel.h>
                     47:
                     48: #include <machine/bus.h>
                     49: #include <machine/intr.h>
                     50:
                     51: #include <dev/i2c/i2cvar.h>
                     52:
                     53: #include <arm/xscale/iopi2creg.h>
                     54: #include <arm/xscale/iopi2cvar.h>
                     55:
                     56: static int iopiic_acquire_bus(void *, int);
                     57: static void iopiic_release_bus(void *, int);
                     58:
                     59: static int iopiic_send_start(void *, int);
                     60: static int iopiic_send_stop(void *, int);
                     61: static int iopiic_initiate_xfer(void *, uint16_t, int);
                     62: static int iopiic_read_byte(void *, uint8_t *, int);
                     63: static int iopiic_write_byte(void *, uint8_t, int);
                     64:
                     65: struct cfdriver iopiic_cd = {
                     66:        NULL, "iopiic", DV_DULL
                     67: };
                     68:
                     69: void
                     70: iopiic_attach(struct iopiic_softc *sc)
                     71: {
                     72:        struct i2cbus_attach_args iba;
                     73:
                     74:        sc->sc_i2c.ic_exec = NULL;
                     75:        sc->sc_i2c.ic_cookie = sc;
                     76:        sc->sc_i2c.ic_acquire_bus = iopiic_acquire_bus;
                     77:        sc->sc_i2c.ic_release_bus = iopiic_release_bus;
                     78:        sc->sc_i2c.ic_send_start = iopiic_send_start;
                     79:        sc->sc_i2c.ic_send_stop = iopiic_send_stop;
                     80:        sc->sc_i2c.ic_initiate_xfer = iopiic_initiate_xfer;
                     81:        sc->sc_i2c.ic_read_byte = iopiic_read_byte;
                     82:        sc->sc_i2c.ic_write_byte = iopiic_write_byte;
                     83:
                     84:        bzero(&iba, sizeof iba);
                     85:        iba.iba_name = "iic";
                     86:        iba.iba_tag = &sc->sc_i2c;
                     87:        (void) config_found(&sc->sc_dev, &iba, iicbus_print);
                     88: }
                     89:
                     90: static int
                     91: iopiic_acquire_bus(void *cookie, int flags)
                     92: {
                     93:        struct iopiic_softc *sc = cookie;
                     94:
                     95:        /* XXX What should we do for the polling case? */
                     96:        if (flags & I2C_F_POLL)
                     97:                return (0);
                     98:
                     99:        return (lockmgr(&sc->sc_buslock, LK_EXCLUSIVE, NULL));
                    100: }
                    101:
                    102: static void
                    103: iopiic_release_bus(void *cookie, int flags)
                    104: {
                    105:        struct iopiic_softc *sc = cookie;
                    106:
                    107:        /* XXX See above. */
                    108:        if (flags & I2C_F_POLL)
                    109:                return;
                    110:
                    111:        (void) lockmgr(&sc->sc_buslock, LK_RELEASE, NULL);
                    112: }
                    113:
                    114: #define        IOPIIC_TIMEOUT          100     /* protocol timeout, in uSecs */
                    115:
                    116: static int
                    117: iopiic_wait(struct iopiic_softc *sc, int bit, int flags)
                    118: {
                    119:        uint32_t isr;
                    120:        int timeout, error=0;
                    121:
                    122:        /* XXX We never sleep, we always poll.  Fix me. */
                    123:
                    124:        /*
                    125:         * For some reason, we seem to run into problems if we poll
                    126:         * the ISR while the transfer is in progress--at least on the
                    127:         * i80312.  The condition that we're looking for never seems
                    128:         * to appear on a read, and it's not clear why; perhaps reads
                    129:         * of the I2C register file interfere with its proper operation?
                    130:         * For now, just delay for a while up front.
                    131:         *
                    132:         * We _really_ need this to be interrupt-driven, but a problem
                    133:         * with that is that the i80312 has no way to mask interrupts...
                    134:         * So we need to deal with that.  For DMA and AAU, too, for that
                    135:         * matter.
                    136:         * Note that delay(100) doesn't quite work on the npwr w/ m41t00.
                    137:         */
                    138:        delay(200);
                    139:        for (timeout = IOPIIC_TIMEOUT; timeout != 0; timeout--) {
                    140:                isr = bus_space_read_4(sc->sc_st, sc->sc_sh, IIC_ISR);
                    141:                if (isr & (bit | IIC_ISR_BED))
                    142:                        break;
                    143:                delay(1);
                    144:        }
                    145:
                    146:        if (isr & (IIC_ISR_BED | (bit & IIC_ISR_ALD)))
                    147:                error = EIO;
                    148:        else if (isr & (bit & ~IIC_ISR_ALD))
                    149:                error = 0;
                    150:        else
                    151:                error = ETIMEDOUT;
                    152:
                    153: #if 0
                    154:        if (error)
                    155:                printf("%s: iopiic_wait, (%08x) error %d: ISR = 0x%08x\n",
                    156:                    sc->sc_dev.dv_xname, bit, error, isr);
                    157: #endif
                    158:
                    159:        /*
                    160:         * The IIC_ISR is Read/Clear apart from the bottom 4 bits, which are
                    161:         * read-only. So simply write back our copy of the ISR to clear any
                    162:         * latched status.
                    163:         */
                    164:        bus_space_write_4(sc->sc_st, sc->sc_sh, IIC_ISR, isr);
                    165:
                    166:        return (error);
                    167: }
                    168:
                    169: static int
                    170: iopiic_send_start(void *cookie, int flags)
                    171: {
                    172:        struct iopiic_softc *sc = cookie;
                    173:
                    174:        /*
                    175:         * This may only work in conjunction with a data transfer;
                    176:         * we might need to un-export the "start" primitive.
                    177:         */
                    178:        bus_space_write_4(sc->sc_st, sc->sc_sh, IIC_ICR,
                    179:            sc->sc_icr | IIC_ICR_START);
                    180:        delay(IOPIIC_TIMEOUT);
                    181:
                    182:        return (0);
                    183: }
                    184:
                    185: static int
                    186: iopiic_send_stop(void *cookie, int flags)
                    187: {
                    188:        struct iopiic_softc *sc = cookie;
                    189:
                    190:        /*
                    191:         * The STOP bit is only used in conjunction with
                    192:         * a data transfer, so we need to use MA in this
                    193:         * case.
                    194:         *
                    195:         * Consider adding an I2C_F_STOP so we can
                    196:         * do a read-with-STOP and write-with-STOP.
                    197:         */
                    198:        bus_space_write_4(sc->sc_st, sc->sc_sh, IIC_ICR,
                    199:            sc->sc_icr | IIC_ICR_MA);
                    200:        delay(IOPIIC_TIMEOUT);
                    201:
                    202:        return (0);
                    203: }
                    204:
                    205: static int
                    206: iopiic_initiate_xfer(void *cookie, uint16_t addr, int flags)
                    207: {
                    208:        struct iopiic_softc *sc = cookie;
                    209:        int error, rd_req = (flags & I2C_F_READ) != 0;
                    210:        uint32_t idbr;
                    211:
                    212:        /* We only support 7-bit addressing. */
                    213:        if ((addr & 0x78) == 0x78)
                    214:                return (EINVAL);
                    215:
                    216:        idbr = (addr << 1) | (rd_req ? 1 : 0);
                    217:        bus_space_write_4(sc->sc_st, sc->sc_sh, IIC_IDBR, idbr);
                    218:        bus_space_write_4(sc->sc_st, sc->sc_sh, IIC_ICR,
                    219:            sc->sc_icr | IIC_ICR_START | IIC_ICR_TB);
                    220:
                    221:        error = iopiic_wait(sc, IIC_ISR_ITE, flags);
                    222: #if 0
                    223:        if (error)
                    224:                printf("%s: failed to initiate %s xfer\n", sc->sc_dev.dv_xname,
                    225:                    rd_req ? "read" : "write");
                    226: #endif
                    227:        return (error);
                    228: }
                    229:
                    230: static int
                    231: iopiic_read_byte(void *cookie, uint8_t *bytep, int flags)
                    232: {
                    233:        struct iopiic_softc *sc = cookie;
                    234:        int error, last_byte = (flags & I2C_F_LAST) != 0,
                    235:            send_stop = (flags & I2C_F_STOP) != 0;
                    236:
                    237:        bus_space_write_4(sc->sc_st, sc->sc_sh, IIC_ICR,
                    238:            sc->sc_icr | IIC_ICR_TB | (last_byte ? IIC_ICR_NACK : 0) |
                    239:            (send_stop ? IIC_ICR_STOP : 0));
                    240:        if ((error = iopiic_wait(sc, IIC_ISR_IRF | IIC_ISR_ALD, flags)) == 0)
                    241:                *bytep = bus_space_read_4(sc->sc_st, sc->sc_sh, IIC_IDBR);
                    242: #if 0
                    243:        if (error)
                    244:                printf("%s: read byte failed\n", sc->sc_dev.dv_xname);
                    245: #endif
                    246:
                    247:        return (error);
                    248: }
                    249:
                    250: static int
                    251: iopiic_write_byte(void *cookie, uint8_t byte, int flags)
                    252: {
                    253:        struct iopiic_softc *sc = cookie;
                    254:        int error, send_stop = (flags & I2C_F_STOP) != 0;
                    255:
                    256:        bus_space_write_4(sc->sc_st, sc->sc_sh, IIC_IDBR, byte);
                    257:        bus_space_write_4(sc->sc_st, sc->sc_sh, IIC_ICR,
                    258:            sc->sc_icr | IIC_ICR_TB | (send_stop ? IIC_ICR_STOP : 0));
                    259:        error = iopiic_wait(sc, IIC_ISR_ITE | IIC_ISR_ALD, flags);
                    260:
                    261: #if 0
                    262:        if (error)
                    263:                printf("%s: write byte failed\n", sc->sc_dev.dv_xname);
                    264: #endif
                    265:
                    266:        return (error);
                    267: }

CVSweb