[BACK]Return to i2c_bitbang.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev / i2c

Annotation of src/sys/dev/i2c/i2c_bitbang.c, Revision 1.4.4.1

1.4.4.1 ! ad          1: /*     $NetBSD: i2c_bitbang.c,v 1.6 2006/11/16 01:32:50 christos 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: /*
                     39:  * Common module for bit-bang'ing an I2C bus.
                     40:  */
                     41:
                     42: #include <sys/param.h>
                     43:
                     44: #include <dev/i2c/i2cvar.h>
                     45: #include <dev/i2c/i2c_bitbang.h>
                     46:
1.3       christos   47: #define        SETBITS(x)      ops->ibo_set_bits(v, (x))
1.1       thorpej    48: #define        DIR(x)          ops->ibo_set_dir(v, (x))
                     49: #define        READ            ops->ibo_read_bits(v)
                     50:
                     51: #define        SDA             ops->ibo_bits[I2C_BIT_SDA]      /* i2c signal */
                     52: #define        SCL             ops->ibo_bits[I2C_BIT_SCL]      /* i2c signal */
                     53: #define        OUTPUT          ops->ibo_bits[I2C_BIT_OUTPUT]   /* SDA is output */
                     54: #define        INPUT           ops->ibo_bits[I2C_BIT_INPUT]    /* SDA is input */
                     55:
                     56: /*ARGSUSED*/
                     57: int
                     58: i2c_bitbang_send_start(void *v, int flags, i2c_bitbang_ops_t ops)
                     59: {
                     60:
                     61:        DIR(OUTPUT);
                     62:
1.3       christos   63:        SETBITS(SDA | SCL);
1.1       thorpej    64:        delay(5);               /* bus free time (4.7 uS) */
1.3       christos   65:        SETBITS(      SCL);
1.1       thorpej    66:        delay(4);               /* start hold time (4.0 uS) */
1.3       christos   67:        SETBITS(        0);
1.1       thorpej    68:        delay(5);               /* clock low time (4.7 uS) */
                     69:
                     70:        return (0);
                     71: }
                     72:
                     73: /*ARGSUSED*/
                     74: int
                     75: i2c_bitbang_send_stop(void *v, int flags, i2c_bitbang_ops_t ops)
                     76: {
                     77:
                     78:        DIR(OUTPUT);
                     79:
1.3       christos   80:        SETBITS(      SCL);
1.1       thorpej    81:        delay(4);               /* stop setup time (4.0 uS) */
1.3       christos   82:        SETBITS(SDA | SCL);
1.1       thorpej    83:
                     84:        return (0);
                     85: }
                     86:
                     87: int
                     88: i2c_bitbang_initiate_xfer(void *v, i2c_addr_t addr, int flags,
                     89:     i2c_bitbang_ops_t ops)
                     90: {
                     91:
1.4       gdamore    92:        if (addr < 0x80) {
                     93:                uint8_t i2caddr;
1.1       thorpej    94:
1.4       gdamore    95:                /* disallow the 10-bit address prefix */
                     96:                if ((addr & 0x78) == 0x78)
                     97:                        return EINVAL;
                     98:                i2caddr = (addr << 1) | ((flags & I2C_F_READ) ? 1 : 0);
                     99:                (void) i2c_bitbang_send_start(v, flags, ops);
                    100:
                    101:                return (i2c_bitbang_write_byte(v, i2caddr,
                    102:                            flags & ~I2C_F_STOP, ops));
                    103:
                    104:        } else if (addr < 0x400) {
                    105:                uint16_t        i2caddr;
                    106:                int             rv;
                    107:
                    108:                i2caddr = (addr << 1) | ((flags & I2C_F_READ) ? 1 : 0) |
                    109:                    0xf000;
                    110:
                    111:                (void) i2c_bitbang_send_start(v, flags, ops);
                    112:                rv = i2c_bitbang_write_byte(v, i2caddr >> 8,
                    113:                    flags & ~I2C_F_STOP, ops);
                    114:                /* did a slave ack the 10-bit prefix? */
                    115:                if (rv != 0)
                    116:                        return rv;
                    117:
                    118:                /* send the lower 7-bits (+ read/write mode) */
                    119:                return (i2c_bitbang_write_byte(v, i2caddr & 0xff,
                    120:                            flags & ~I2C_F_STOP, ops));
1.1       thorpej   121:
1.4       gdamore   122:        } else
                    123:                return EINVAL;
1.1       thorpej   124: }
                    125:
                    126: int
                    127: i2c_bitbang_read_byte(void *v, uint8_t *valp, int flags,
                    128:     i2c_bitbang_ops_t ops)
                    129: {
                    130:        int i;
                    131:        uint8_t val = 0;
                    132:        uint32_t bit;
                    133:
                    134:        DIR(INPUT);
1.3       christos  135:        SETBITS(SDA      );
1.1       thorpej   136:
                    137:        for (i = 0; i < 8; i++) {
                    138:                val <<= 1;
1.3       christos  139:                SETBITS(SDA | SCL);
1.1       thorpej   140:                delay(4);       /* clock high time (4.0 uS) */
                    141:                if (READ & SDA)
                    142:                        val |= 1;
1.3       christos  143:                SETBITS(SDA      );
1.1       thorpej   144:                delay(5);       /* clock low time (4.7 uS) */
                    145:        }
                    146:
                    147:        bit = (flags & I2C_F_LAST) ? SDA : 0;
                    148:        DIR(OUTPUT);
1.3       christos  149:        SETBITS(bit      );
1.1       thorpej   150:        delay(1);       /* data setup time (250 nS) */
1.3       christos  151:        SETBITS(bit | SCL);
1.1       thorpej   152:        delay(4);       /* clock high time (4.0 uS) */
1.3       christos  153:        SETBITS(bit      );
1.1       thorpej   154:        delay(5);       /* clock low time (4.7 uS) */
                    155:
                    156:        DIR(INPUT);
1.3       christos  157:        SETBITS(SDA      );
1.1       thorpej   158:        delay(5);
                    159:
                    160:        if ((flags & (I2C_F_STOP | I2C_F_LAST)) == (I2C_F_STOP | I2C_F_LAST))
                    161:                (void) i2c_bitbang_send_stop(v, flags, ops);
                    162:
                    163:        *valp = val;
                    164:        return (0);
                    165: }
                    166:
                    167: int
                    168: i2c_bitbang_write_byte(void *v, uint8_t val, int flags,
                    169:     i2c_bitbang_ops_t ops)
                    170: {
                    171:        uint32_t bit;
                    172:        uint8_t mask;
                    173:        int error;
                    174:
                    175:        DIR(OUTPUT);
                    176:
                    177:        for (mask = 0x80; mask != 0; mask >>= 1) {
                    178:                bit = (val & mask) ? SDA : 0;
1.3       christos  179:                SETBITS(bit      );
1.1       thorpej   180:                delay(1);       /* data setup time (250 nS) */
1.3       christos  181:                SETBITS(bit | SCL);
1.1       thorpej   182:                delay(4);       /* clock high time (4.0 uS) */
1.3       christos  183:                SETBITS(bit      );
1.1       thorpej   184:                delay(5);       /* clock low time (4.7 uS) */
                    185:        }
                    186:
                    187:        DIR(INPUT);
                    188:
1.3       christos  189:        SETBITS(SDA      );
1.1       thorpej   190:        delay(5);
1.3       christos  191:        SETBITS(SDA | SCL);
1.1       thorpej   192:        delay(4);
                    193:        error = (READ & SDA) ? EIO : 0;
1.3       christos  194:        SETBITS(SDA      );
1.1       thorpej   195:        delay(5);
                    196:
                    197:        if (flags & I2C_F_STOP)
                    198:                (void) i2c_bitbang_send_stop(v, flags, ops);
                    199:
                    200:        return (error);
                    201: }

CVSweb <webmaster@jp.NetBSD.org>