176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>. 376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * This program is free software; you can redistribute it and/or 576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * modify it under the terms of the GNU General Public License as 676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * published by the Free Software Foundation; either version 2 of the 776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * License, or any later version. 876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * This program is distributed in the hope that it will be useful, but 1076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * WITHOUT ANY WARRANTY; without even the implied warranty of 1176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * General Public License for more details. 1376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 1476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * You should have received a copy of the GNU General Public License 1576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * along with this program; if not, write to the Free Software 1676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 1776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 1876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 1976d05dc695b06c4e987bb8078f78032441e1430cGreg HartmanFILE_LICENCE ( GPL2_OR_LATER ); 2076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 2176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <stddef.h> 2276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <stdint.h> 2376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <errno.h> 2476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <string.h> 2576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <assert.h> 2676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <unistd.h> 2776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <gpxe/bitbash.h> 2876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <gpxe/i2c.h> 2976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 3076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** @file 3176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 3276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * I2C bit-bashing interface 3376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 3476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * This implements a simple I2C master via a bit-bashing interface 3576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * that provides two lines: SCL (clock) and SDA (data). 3676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 3776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 3876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** 3976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Delay between output state changes 4076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 4176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Max rated i2c speed (for the basic i2c protocol) is 100kbps, 4276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * i.e. 200k clock transitions per second. 4376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 4476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void i2c_delay ( void ) { 4576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman udelay ( I2C_UDELAY ); 4676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 4776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 4876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** 4976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Set state of I2C SCL line 5076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 5176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v basher Bit-bashing interface 5276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v state New state of SCL 5376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 5476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void setscl ( struct bit_basher *basher, int state ) { 5576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DBG2 ( "%c", ( state ? '/' : '\\' ) ); 5676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman write_bit ( basher, I2C_BIT_SCL, state ); 5776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman i2c_delay(); 5876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 5976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 6076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** 6176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Set state of I2C SDA line 6276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 6376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v basher Bit-bashing interface 6476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v state New state of SDA 6576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 6676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void setsda ( struct bit_basher *basher, int state ) { 6776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DBG2 ( "%c", ( state ? '1' : '0' ) ); 6876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman write_bit ( basher, I2C_BIT_SDA, state ); 6976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman i2c_delay(); 7076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 7176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 7276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** 7376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Get state of I2C SDA line 7476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 7576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v basher Bit-bashing interface 7676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @ret state State of SDA 7776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 7876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int getsda ( struct bit_basher *basher ) { 7976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int state; 8076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman state = read_bit ( basher, I2C_BIT_SDA ); 8176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DBG2 ( "%c", ( state ? '+' : '-' ) ); 8276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return state; 8376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 8476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 8576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** 8676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Send an I2C start condition 8776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 8876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v basher Bit-bashing interface 8976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 9076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void i2c_start ( struct bit_basher *basher ) { 9176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman setscl ( basher, 1 ); 9276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman setsda ( basher, 0 ); 9376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman setscl ( basher, 0 ); 9476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman setsda ( basher, 1 ); 9576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 9676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 9776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** 9876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Send an I2C data bit 9976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 10076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v basher Bit-bashing interface 10176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v bit Bit to send 10276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 10376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void i2c_send_bit ( struct bit_basher *basher, int bit ) { 10476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman setsda ( basher, bit ); 10576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman setscl ( basher, 1 ); 10676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman setscl ( basher, 0 ); 10776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman setsda ( basher, 1 ); 10876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 10976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 11076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** 11176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Receive an I2C data bit 11276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 11376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v basher Bit-bashing interface 11476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @ret bit Received bit 11576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 11676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int i2c_recv_bit ( struct bit_basher *basher ) { 11776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int bit; 11876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 11976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman setscl ( basher, 1 ); 12076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman bit = getsda ( basher ); 12176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman setscl ( basher, 0 ); 12276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return bit; 12376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 12476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 12576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** 12676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Send an I2C stop condition 12776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 12876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v basher Bit-bashing interface 12976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 13076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void i2c_stop ( struct bit_basher *basher ) { 13176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman setsda ( basher, 0 ); 13276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman setscl ( basher, 1 ); 13376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman setsda ( basher, 1 ); 13476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 13576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 13676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** 13776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Send byte via I2C bus and check for acknowledgement 13876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 13976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v basher Bit-bashing interface 14076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v byte Byte to send 14176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @ret rc Return status code 14276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 14376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Sends a byte via the I2C bus and checks for an acknowledgement from 14476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * the slave device. 14576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 14676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int i2c_send_byte ( struct bit_basher *basher, uint8_t byte ) { 14776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int i; 14876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int ack; 14976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 15076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Send byte */ 15176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DBG2 ( "[send %02x]", byte ); 15276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for ( i = 8 ; i ; i-- ) { 15376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman i2c_send_bit ( basher, byte & 0x80 ); 15476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman byte <<= 1; 15576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 15676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 15776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Check for acknowledgement from slave */ 15876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ack = ( i2c_recv_bit ( basher ) == 0 ); 15976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DBG2 ( "%s", ( ack ? "[acked]" : "[not acked]" ) ); 16076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 16176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return ( ack ? 0 : -EIO ); 16276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 16376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 16476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** 16576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Receive byte via I2C bus 16676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 16776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v basher Bit-bashing interface 16876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @ret byte Received byte 16976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 17076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Receives a byte via the I2C bus and sends NACK to the slave device. 17176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 17276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic uint8_t i2c_recv_byte ( struct bit_basher *basher ) { 17376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman uint8_t byte = 0; 17476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int i; 17576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 17676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Receive byte */ 17776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for ( i = 8 ; i ; i-- ) { 17876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman byte <<= 1; 17976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman byte |= ( i2c_recv_bit ( basher ) & 0x1 ); 18076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 18176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 18276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Send NACK */ 18376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman i2c_send_bit ( basher, 1 ); 18476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 18576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DBG2 ( "[rcvd %02x]", byte ); 18676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return byte; 18776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 18876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 18976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** 19076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Select I2C device for reading or writing 19176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 19276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v basher Bit-bashing interface 19376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v i2cdev I2C device 19476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v offset Starting offset within the device 19576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v direction I2C_READ or I2C_WRITE 19676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @ret rc Return status code 19776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 19876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int i2c_select ( struct bit_basher *basher, struct i2c_device *i2cdev, 19976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman unsigned int offset, unsigned int direction ) { 20076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman unsigned int address; 20176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int shift; 20276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman unsigned int byte; 20376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int rc; 20476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 20576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman i2c_start ( basher ); 20676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 20776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Calculate address to appear on bus */ 20876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman address = ( ( ( i2cdev->dev_addr | 20976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ( offset >> ( 8 * i2cdev->word_addr_len ) ) ) << 1 ) 21076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman | direction ); 21176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 21276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Send address a byte at a time */ 21376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for ( shift = ( 8 * ( i2cdev->dev_addr_len - 1 ) ) ; 21476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman shift >= 0 ; shift -= 8 ) { 21576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman byte = ( ( address >> shift ) & 0xff ); 21676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if ( ( rc = i2c_send_byte ( basher, byte ) ) != 0 ) 21776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return rc; 21876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 21976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 22076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 0; 22176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 22276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 22376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** 22476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Reset I2C bus 22576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 22676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v basher Bit-bashing interface 22776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @ret rc Return status code 22876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 22976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * i2c devices often don't have a reset line, so even a reboot or 23076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * system power cycle is sometimes not enough to bring them back to a 23176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * known state. 23276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 23376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int i2c_reset ( struct bit_basher *basher ) { 23476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman unsigned int i; 23576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int sda; 23676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 23776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Clock through several cycles, waiting for an opportunity to 23876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * pull SDA low while SCL is high (which creates a start 23976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * condition). 24076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 24176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman setscl ( basher, 0 ); 24276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman setsda ( basher, 1 ); 24376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for ( i = 0 ; i < I2C_RESET_MAX_CYCLES ; i++ ) { 24476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman setscl ( basher, 1 ); 24576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sda = getsda ( basher ); 24676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if ( sda ) { 24776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Now that the device will see a start, issue it */ 24876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman i2c_start ( basher ); 24976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Stop the bus to leave it in a known good state */ 25076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman i2c_stop ( basher ); 25176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DBGC ( basher, "I2CBIT %p reset after %d attempts\n", 25276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman basher, ( i + 1 ) ); 25376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 0; 25476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 25576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman setscl ( basher, 0 ); 25676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 25776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 25876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DBGC ( basher, "I2CBIT %p could not reset after %d attempts\n", 25976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman basher, i ); 26076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return -ETIMEDOUT; 26176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 26276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 26376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** 26476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Read data from I2C device via bit-bashing interface 26576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 26676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v i2c I2C interface 26776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v i2cdev I2C device 26876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v offset Starting offset within the device 26976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v data Data buffer 27076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v len Length of data buffer 27176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @ret rc Return status code 27276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 27376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Note that attempting to read zero bytes of data is a valid way to 27476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * check for I2C device presence. 27576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 27676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int i2c_bit_read ( struct i2c_interface *i2c, 27776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct i2c_device *i2cdev, unsigned int offset, 27876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman uint8_t *data, unsigned int len ) { 27976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct i2c_bit_basher *i2cbit 28076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman = container_of ( i2c, struct i2c_bit_basher, i2c ); 28176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct bit_basher *basher = &i2cbit->basher; 28276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int rc = 0; 28376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 28476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DBGC ( basher, "I2CBIT %p reading from device %x: ", 28576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman basher, i2cdev->dev_addr ); 28676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 28776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for ( ; ; data++, offset++ ) { 28876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 28976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Select device for writing */ 29076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if ( ( rc = i2c_select ( basher, i2cdev, offset, 29176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman I2C_WRITE ) ) != 0 ) 29276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 29376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 29476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Abort at end of data */ 29576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if ( ! ( len-- ) ) 29676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 29776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 29876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Select offset */ 29976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if ( ( rc = i2c_send_byte ( basher, offset ) ) != 0 ) 30076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 30176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 30276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Select device for reading */ 30376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if ( ( rc = i2c_select ( basher, i2cdev, offset, 30476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman I2C_READ ) ) != 0 ) 30576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 30676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 30776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Read byte */ 30876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *data = i2c_recv_byte ( basher ); 30976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DBGC ( basher, "%02x ", *data ); 31076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 31176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 31276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DBGC ( basher, "%s\n", ( rc ? "failed" : "" ) ); 31376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman i2c_stop ( basher ); 31476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return rc; 31576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 31676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 31776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** 31876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Write data to I2C device via bit-bashing interface 31976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 32076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v i2c I2C interface 32176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v i2cdev I2C device 32276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v offset Starting offset within the device 32376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v data Data buffer 32476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v len Length of data buffer 32576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @ret rc Return status code 32676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 32776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Note that attempting to write zero bytes of data is a valid way to 32876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * check for I2C device presence. 32976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 33076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic int i2c_bit_write ( struct i2c_interface *i2c, 33176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct i2c_device *i2cdev, unsigned int offset, 33276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman const uint8_t *data, unsigned int len ) { 33376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct i2c_bit_basher *i2cbit 33476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman = container_of ( i2c, struct i2c_bit_basher, i2c ); 33576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct bit_basher *basher = &i2cbit->basher; 33676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int rc = 0; 33776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 33876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DBGC ( basher, "I2CBIT %p writing to device %x: ", 33976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman basher, i2cdev->dev_addr ); 34076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 34176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for ( ; ; data++, offset++ ) { 34276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 34376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Select device for writing */ 34476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if ( ( rc = i2c_select ( basher, i2cdev, offset, 34576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman I2C_WRITE ) ) != 0 ) 34676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 34776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 34876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Abort at end of data */ 34976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if ( ! ( len-- ) ) 35076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 35176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 35276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Select offset */ 35376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if ( ( rc = i2c_send_byte ( basher, offset ) ) != 0 ) 35476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 35576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 35676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Write data to device */ 35776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DBGC ( basher, "%02x ", *data ); 35876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if ( ( rc = i2c_send_byte ( basher, *data ) ) != 0 ) 35976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 36076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 36176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 36276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DBGC ( basher, "%s\n", ( rc ? "failed" : "" ) ); 36376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman i2c_stop ( basher ); 36476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return rc; 36576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 36676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 36776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** 36876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Initialise I2C bit-bashing interface 36976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 37076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v i2cbit I2C bit-bashing interface 37176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v bash_op Bit-basher operations 37276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 37376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanint init_i2c_bit_basher ( struct i2c_bit_basher *i2cbit, 37476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct bit_basher_operations *bash_op ) { 37576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct bit_basher *basher = &i2cbit->basher; 37676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int rc; 37776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 37876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Initialise data structures */ 37976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman basher->op = bash_op; 38076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman assert ( basher->op->read != NULL ); 38176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman assert ( basher->op->write != NULL ); 38276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman i2cbit->i2c.read = i2c_bit_read; 38376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman i2cbit->i2c.write = i2c_bit_write; 38476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 38576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Reset I2C bus */ 38676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if ( ( rc = i2c_reset ( basher ) ) != 0 ) { 38776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DBGC ( basher, "I2CBIT %p could not reset I2C bus: %s\n", 38876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman basher, strerror ( rc ) ); 38976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return rc; 39076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 39176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 39276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return 0; 39376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 394