[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     ! 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