Annotation of qemu/roms/ipxe/src/drivers/bitbash/i2c_bit.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (C) 2006 Michael Brown <[email protected]>.
        !             3:  *
        !             4:  * This program is free software; you can redistribute it and/or
        !             5:  * modify it under the terms of the GNU General Public License as
        !             6:  * published by the Free Software Foundation; either version 2 of the
        !             7:  * License, or any later version.
        !             8:  *
        !             9:  * This program is distributed in the hope that it will be useful, but
        !            10:  * WITHOUT ANY WARRANTY; without even the implied warranty of
        !            11:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
        !            12:  * General Public License for more details.
        !            13:  *
        !            14:  * You should have received a copy of the GNU General Public License
        !            15:  * along with this program; if not, write to the Free Software
        !            16:  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
        !            17:  */
        !            18: 
        !            19: FILE_LICENCE ( GPL2_OR_LATER );
        !            20: 
        !            21: #include <stddef.h>
        !            22: #include <stdint.h>
        !            23: #include <errno.h>
        !            24: #include <string.h>
        !            25: #include <assert.h>
        !            26: #include <unistd.h>
        !            27: #include <ipxe/bitbash.h>
        !            28: #include <ipxe/i2c.h>
        !            29: 
        !            30: /** @file
        !            31:  *
        !            32:  * I2C bit-bashing interface
        !            33:  *
        !            34:  * This implements a simple I2C master via a bit-bashing interface
        !            35:  * that provides two lines: SCL (clock) and SDA (data).
        !            36:  */
        !            37: 
        !            38: /**
        !            39:  * Delay between output state changes
        !            40:  *
        !            41:  * Max rated i2c speed (for the basic i2c protocol) is 100kbps,
        !            42:  * i.e. 200k clock transitions per second.
        !            43:  */
        !            44: static void i2c_delay ( void ) {
        !            45:        udelay ( I2C_UDELAY );
        !            46: }
        !            47: 
        !            48: /**
        !            49:  * Set state of I2C SCL line
        !            50:  *
        !            51:  * @v basher           Bit-bashing interface
        !            52:  * @v state            New state of SCL
        !            53:  */
        !            54: static void setscl ( struct bit_basher *basher, int state ) {
        !            55:        DBG2 ( "%c", ( state ? '/' : '\\' ) );
        !            56:        write_bit ( basher, I2C_BIT_SCL, state );
        !            57:        i2c_delay();
        !            58: }
        !            59: 
        !            60: /**
        !            61:  * Set state of I2C SDA line
        !            62:  *
        !            63:  * @v basher           Bit-bashing interface
        !            64:  * @v state            New state of SDA
        !            65:  */
        !            66: static void setsda ( struct bit_basher *basher, int state ) {
        !            67:        DBG2 ( "%c", ( state ? '1' : '0' ) );
        !            68:        write_bit ( basher, I2C_BIT_SDA, state );
        !            69:        i2c_delay();
        !            70: }
        !            71: 
        !            72: /**
        !            73:  * Get state of I2C SDA line
        !            74:  *
        !            75:  * @v basher           Bit-bashing interface
        !            76:  * @ret state          State of SDA
        !            77:  */
        !            78: static int getsda ( struct bit_basher *basher ) {
        !            79:        int state;
        !            80:        state = read_bit ( basher, I2C_BIT_SDA );
        !            81:        DBG2 ( "%c", ( state ? '+' : '-' ) );
        !            82:        return state;
        !            83: }
        !            84: 
        !            85: /**
        !            86:  * Send an I2C start condition
        !            87:  *
        !            88:  * @v basher           Bit-bashing interface
        !            89:  */
        !            90: static void i2c_start ( struct bit_basher *basher ) {
        !            91:        setscl ( basher, 1 );
        !            92:        setsda ( basher, 0 );
        !            93:        setscl ( basher, 0 );
        !            94:        setsda ( basher, 1 );
        !            95: }
        !            96: 
        !            97: /**
        !            98:  * Send an I2C data bit
        !            99:  *
        !           100:  * @v basher           Bit-bashing interface
        !           101:  * @v bit              Bit to send
        !           102:  */
        !           103: static void i2c_send_bit ( struct bit_basher *basher, int bit ) {
        !           104:        setsda ( basher, bit );
        !           105:        setscl ( basher, 1 );
        !           106:        setscl ( basher, 0 );
        !           107:        setsda ( basher, 1 );
        !           108: }
        !           109: 
        !           110: /**
        !           111:  * Receive an I2C data bit
        !           112:  *
        !           113:  * @v basher           Bit-bashing interface
        !           114:  * @ret bit            Received bit
        !           115:  */
        !           116: static int i2c_recv_bit ( struct bit_basher *basher ) {
        !           117:        int bit;
        !           118: 
        !           119:        setscl ( basher, 1 );
        !           120:        bit = getsda ( basher );
        !           121:        setscl ( basher, 0 );
        !           122:        return bit;
        !           123: }
        !           124: 
        !           125: /**
        !           126:  * Send an I2C stop condition
        !           127:  *
        !           128:  * @v basher           Bit-bashing interface
        !           129:  */
        !           130: static void i2c_stop ( struct bit_basher *basher ) {
        !           131:        setsda ( basher, 0 );
        !           132:        setscl ( basher, 1 );
        !           133:        setsda ( basher, 1 );
        !           134: }
        !           135: 
        !           136: /**
        !           137:  * Send byte via I2C bus and check for acknowledgement
        !           138:  *
        !           139:  * @v basher           Bit-bashing interface
        !           140:  * @v byte             Byte to send
        !           141:  * @ret rc             Return status code
        !           142:  *
        !           143:  * Sends a byte via the I2C bus and checks for an acknowledgement from
        !           144:  * the slave device.
        !           145:  */
        !           146: static int i2c_send_byte ( struct bit_basher *basher, uint8_t byte ) {
        !           147:        int i;
        !           148:        int ack;
        !           149: 
        !           150:        /* Send byte */
        !           151:        DBG2 ( "[send %02x]", byte );
        !           152:        for ( i = 8 ; i ; i-- ) {
        !           153:                i2c_send_bit ( basher, byte & 0x80 );
        !           154:                byte <<= 1;
        !           155:        }
        !           156: 
        !           157:        /* Check for acknowledgement from slave */
        !           158:        ack = ( i2c_recv_bit ( basher ) == 0 );
        !           159:        DBG2 ( "%s", ( ack ? "[acked]" : "[not acked]" ) );
        !           160: 
        !           161:        return ( ack ? 0 : -EIO );
        !           162: }
        !           163: 
        !           164: /**
        !           165:  * Receive byte via I2C bus
        !           166:  *
        !           167:  * @v basher           Bit-bashing interface
        !           168:  * @ret byte           Received byte
        !           169:  *
        !           170:  * Receives a byte via the I2C bus and sends NACK to the slave device.
        !           171:  */
        !           172: static uint8_t i2c_recv_byte ( struct bit_basher *basher ) {
        !           173:        uint8_t byte = 0;
        !           174:        int i;
        !           175: 
        !           176:        /* Receive byte */
        !           177:        for ( i = 8 ; i ; i-- ) {
        !           178:                byte <<= 1;
        !           179:                byte |= ( i2c_recv_bit ( basher ) & 0x1 );
        !           180:        }
        !           181: 
        !           182:        /* Send NACK */
        !           183:        i2c_send_bit ( basher, 1 );
        !           184: 
        !           185:        DBG2 ( "[rcvd %02x]", byte );
        !           186:        return byte;
        !           187: }
        !           188: 
        !           189: /**
        !           190:  * Select I2C device for reading or writing
        !           191:  *
        !           192:  * @v basher           Bit-bashing interface
        !           193:  * @v i2cdev           I2C device
        !           194:  * @v offset           Starting offset within the device
        !           195:  * @v direction                I2C_READ or I2C_WRITE
        !           196:  * @ret rc             Return status code
        !           197:  */
        !           198: static int i2c_select ( struct bit_basher *basher, struct i2c_device *i2cdev,
        !           199:                        unsigned int offset, unsigned int direction ) {
        !           200:        unsigned int address;
        !           201:        int shift;
        !           202:        unsigned int byte;
        !           203:        int rc;
        !           204: 
        !           205:        i2c_start ( basher );
        !           206: 
        !           207:        /* Calculate address to appear on bus */
        !           208:        address = ( ( ( i2cdev->dev_addr |
        !           209:                        ( offset >> ( 8 * i2cdev->word_addr_len ) ) ) << 1 )
        !           210:                    | direction );
        !           211: 
        !           212:        /* Send address a byte at a time */
        !           213:        for ( shift = ( 8 * ( i2cdev->dev_addr_len - 1 ) ) ;
        !           214:              shift >= 0 ; shift -= 8 ) {
        !           215:                byte = ( ( address >> shift ) & 0xff );
        !           216:                if ( ( rc = i2c_send_byte ( basher, byte ) ) != 0 )
        !           217:                        return rc;
        !           218:        }
        !           219: 
        !           220:        return 0;
        !           221: }
        !           222: 
        !           223: /**
        !           224:  * Reset I2C bus
        !           225:  *
        !           226:  * @v basher           Bit-bashing interface
        !           227:  * @ret rc             Return status code
        !           228:  *
        !           229:  * i2c devices often don't have a reset line, so even a reboot or
        !           230:  * system power cycle is sometimes not enough to bring them back to a
        !           231:  * known state.
        !           232:  */
        !           233: static int i2c_reset ( struct bit_basher *basher ) {
        !           234:        unsigned int i;
        !           235:        int sda;
        !           236: 
        !           237:        /* Clock through several cycles, waiting for an opportunity to
        !           238:         * pull SDA low while SCL is high (which creates a start
        !           239:         * condition).
        !           240:         */
        !           241:        setscl ( basher, 0 );
        !           242:        setsda ( basher, 1 );
        !           243:        for ( i = 0 ; i < I2C_RESET_MAX_CYCLES ; i++ ) {
        !           244:                setscl ( basher, 1 );
        !           245:                sda = getsda ( basher );
        !           246:                if ( sda ) {
        !           247:                        /* Now that the device will see a start, issue it */
        !           248:                        i2c_start ( basher );
        !           249:                        /* Stop the bus to leave it in a known good state */
        !           250:                        i2c_stop ( basher );
        !           251:                        DBGC ( basher, "I2CBIT %p reset after %d attempts\n",
        !           252:                               basher, ( i + 1 ) );
        !           253:                        return 0;
        !           254:                }
        !           255:                setscl ( basher, 0 );
        !           256:        }
        !           257: 
        !           258:        DBGC ( basher, "I2CBIT %p could not reset after %d attempts\n",
        !           259:               basher, i );
        !           260:        return -ETIMEDOUT;
        !           261: }
        !           262: 
        !           263: /**
        !           264:  * Read data from I2C device via bit-bashing interface
        !           265:  *
        !           266:  * @v i2c              I2C interface
        !           267:  * @v i2cdev           I2C device
        !           268:  * @v offset           Starting offset within the device
        !           269:  * @v data             Data buffer
        !           270:  * @v len              Length of data buffer
        !           271:  * @ret rc             Return status code
        !           272:  *
        !           273:  * Note that attempting to read zero bytes of data is a valid way to
        !           274:  * check for I2C device presence.
        !           275:  */
        !           276: static int i2c_bit_read ( struct i2c_interface *i2c,
        !           277:                          struct i2c_device *i2cdev, unsigned int offset,
        !           278:                          uint8_t *data, unsigned int len ) {
        !           279:        struct i2c_bit_basher *i2cbit
        !           280:                = container_of ( i2c, struct i2c_bit_basher, i2c );
        !           281:        struct bit_basher *basher = &i2cbit->basher;
        !           282:        int rc = 0;
        !           283: 
        !           284:        DBGC ( basher, "I2CBIT %p reading from device %x: ",
        !           285:               basher, i2cdev->dev_addr );
        !           286: 
        !           287:        for ( ; ; data++, offset++ ) {
        !           288: 
        !           289:                /* Select device for writing */
        !           290:                if ( ( rc = i2c_select ( basher, i2cdev, offset,
        !           291:                                         I2C_WRITE ) ) != 0 )
        !           292:                        break;
        !           293: 
        !           294:                /* Abort at end of data */
        !           295:                if ( ! ( len-- ) )
        !           296:                        break;
        !           297: 
        !           298:                /* Select offset */
        !           299:                if ( ( rc = i2c_send_byte ( basher, offset ) ) != 0 )
        !           300:                        break;
        !           301:                
        !           302:                /* Select device for reading */
        !           303:                if ( ( rc = i2c_select ( basher, i2cdev, offset,
        !           304:                                         I2C_READ ) ) != 0 )
        !           305:                        break;
        !           306: 
        !           307:                /* Read byte */
        !           308:                *data = i2c_recv_byte ( basher );
        !           309:                DBGC ( basher, "%02x ", *data );
        !           310:        }
        !           311:        
        !           312:        DBGC ( basher, "%s\n", ( rc ? "failed" : "" ) );
        !           313:        i2c_stop ( basher );
        !           314:        return rc;
        !           315: }
        !           316: 
        !           317: /**
        !           318:  * Write data to I2C device via bit-bashing interface
        !           319:  *
        !           320:  * @v i2c              I2C interface
        !           321:  * @v i2cdev           I2C device
        !           322:  * @v offset           Starting offset within the device
        !           323:  * @v data             Data buffer
        !           324:  * @v len              Length of data buffer
        !           325:  * @ret rc             Return status code
        !           326:  *
        !           327:  * Note that attempting to write zero bytes of data is a valid way to
        !           328:  * check for I2C device presence.
        !           329:  */
        !           330: static int i2c_bit_write ( struct i2c_interface *i2c,
        !           331:                           struct i2c_device *i2cdev, unsigned int offset,
        !           332:                           const uint8_t *data, unsigned int len ) {
        !           333:        struct i2c_bit_basher *i2cbit
        !           334:                = container_of ( i2c, struct i2c_bit_basher, i2c );
        !           335:        struct bit_basher *basher = &i2cbit->basher;
        !           336:        int rc = 0;
        !           337: 
        !           338:        DBGC ( basher, "I2CBIT %p writing to device %x: ",
        !           339:               basher, i2cdev->dev_addr );
        !           340: 
        !           341:        for ( ; ; data++, offset++ ) {
        !           342: 
        !           343:                /* Select device for writing */
        !           344:                if ( ( rc = i2c_select ( basher, i2cdev, offset,
        !           345:                                         I2C_WRITE ) ) != 0 )
        !           346:                        break;
        !           347:                
        !           348:                /* Abort at end of data */
        !           349:                if ( ! ( len-- ) )
        !           350:                        break;
        !           351: 
        !           352:                /* Select offset */
        !           353:                if ( ( rc = i2c_send_byte ( basher, offset ) ) != 0 )
        !           354:                        break;
        !           355:                
        !           356:                /* Write data to device */
        !           357:                DBGC ( basher, "%02x ", *data );
        !           358:                if ( ( rc = i2c_send_byte ( basher, *data ) ) != 0 )
        !           359:                        break;
        !           360:        }
        !           361:        
        !           362:        DBGC ( basher, "%s\n", ( rc ? "failed" : "" ) );
        !           363:        i2c_stop ( basher );
        !           364:        return rc;
        !           365: }
        !           366: 
        !           367: /**
        !           368:  * Initialise I2C bit-bashing interface
        !           369:  *
        !           370:  * @v i2cbit           I2C bit-bashing interface
        !           371:  * @v bash_op          Bit-basher operations
        !           372:  */
        !           373: int init_i2c_bit_basher ( struct i2c_bit_basher *i2cbit,
        !           374:                          struct bit_basher_operations *bash_op ) {
        !           375:        struct bit_basher *basher = &i2cbit->basher;
        !           376:        int rc;
        !           377: 
        !           378:        /* Initialise data structures */
        !           379:        basher->op = bash_op;
        !           380:        assert ( basher->op->read != NULL );
        !           381:        assert ( basher->op->write != NULL );
        !           382:        i2cbit->i2c.read = i2c_bit_read;
        !           383:        i2cbit->i2c.write = i2c_bit_write;
        !           384: 
        !           385:        /* Reset I2C bus */
        !           386:        if ( ( rc = i2c_reset ( basher ) ) != 0 ) {
        !           387:                DBGC ( basher, "I2CBIT %p could not reset I2C bus: %s\n",
        !           388:                       basher, strerror ( rc ) );
        !           389:                return rc;
        !           390:        }
        !           391: 
        !           392:        return 0;
        !           393: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.