1080c646dSJean-Christophe PLAGNIOL-VILLARD /* 2080c646dSJean-Christophe PLAGNIOL-VILLARD * (C) Copyright 2004 Tundra Semiconductor Corp. 3080c646dSJean-Christophe PLAGNIOL-VILLARD * Author: Alex Bounine 4080c646dSJean-Christophe PLAGNIOL-VILLARD * 5080c646dSJean-Christophe PLAGNIOL-VILLARD * See file CREDITS for list of people who contributed to this 6080c646dSJean-Christophe PLAGNIOL-VILLARD * project. 7080c646dSJean-Christophe PLAGNIOL-VILLARD * 8080c646dSJean-Christophe PLAGNIOL-VILLARD * This program is free software; you can redistribute it and/or 9080c646dSJean-Christophe PLAGNIOL-VILLARD * modify it under the terms of the GNU General Public License as 10080c646dSJean-Christophe PLAGNIOL-VILLARD * published by the Free Software Foundation; either version 2 of 11080c646dSJean-Christophe PLAGNIOL-VILLARD * the License, or (at your option) any later version. 12080c646dSJean-Christophe PLAGNIOL-VILLARD * 13080c646dSJean-Christophe PLAGNIOL-VILLARD * This program is distributed in the hope that it will be useful, 14080c646dSJean-Christophe PLAGNIOL-VILLARD * but WITHOUT ANY WARRANTY; without even the implied warranty of 15080c646dSJean-Christophe PLAGNIOL-VILLARD * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16080c646dSJean-Christophe PLAGNIOL-VILLARD * GNU General Public License for more details. 17080c646dSJean-Christophe PLAGNIOL-VILLARD * 18080c646dSJean-Christophe PLAGNIOL-VILLARD * You should have received a copy of the GNU General Public License 19080c646dSJean-Christophe PLAGNIOL-VILLARD * along with this program; if not, write to the Free Software 20080c646dSJean-Christophe PLAGNIOL-VILLARD * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 21080c646dSJean-Christophe PLAGNIOL-VILLARD * MA 02111-1307 USA 22080c646dSJean-Christophe PLAGNIOL-VILLARD * 23080c646dSJean-Christophe PLAGNIOL-VILLARD */ 24080c646dSJean-Christophe PLAGNIOL-VILLARD 25080c646dSJean-Christophe PLAGNIOL-VILLARD #include <config.h> 26080c646dSJean-Christophe PLAGNIOL-VILLARD #include <common.h> 27080c646dSJean-Christophe PLAGNIOL-VILLARD 28080c646dSJean-Christophe PLAGNIOL-VILLARD #include <tsi108.h> 29080c646dSJean-Christophe PLAGNIOL-VILLARD 30080c646dSJean-Christophe PLAGNIOL-VILLARD #if defined(CONFIG_CMD_I2C) 31080c646dSJean-Christophe PLAGNIOL-VILLARD 32080c646dSJean-Christophe PLAGNIOL-VILLARD #define I2C_DELAY 100000 33080c646dSJean-Christophe PLAGNIOL-VILLARD #undef DEBUG_I2C 34080c646dSJean-Christophe PLAGNIOL-VILLARD 35080c646dSJean-Christophe PLAGNIOL-VILLARD #ifdef DEBUG_I2C 36080c646dSJean-Christophe PLAGNIOL-VILLARD #define DPRINT(x) printf (x) 37080c646dSJean-Christophe PLAGNIOL-VILLARD #else 38080c646dSJean-Christophe PLAGNIOL-VILLARD #define DPRINT(x) 39080c646dSJean-Christophe PLAGNIOL-VILLARD #endif 40080c646dSJean-Christophe PLAGNIOL-VILLARD 41080c646dSJean-Christophe PLAGNIOL-VILLARD /* All functions assume that Tsi108 I2C block is the only master on the bus */ 42080c646dSJean-Christophe PLAGNIOL-VILLARD /* I2C read helper function */ 43080c646dSJean-Christophe PLAGNIOL-VILLARD 44*f0722ee7SPeter Tyser void i2c_init(int speed, int slaveaddr) 45*f0722ee7SPeter Tyser { 46*f0722ee7SPeter Tyser /* 47*f0722ee7SPeter Tyser * The TSI108 has a fixed I2C clock rate and doesn't support slave 48*f0722ee7SPeter Tyser * operation. This function only exists as a stub to fit into the 49*f0722ee7SPeter Tyser * U-Boot I2C API. 50*f0722ee7SPeter Tyser */ 51*f0722ee7SPeter Tyser } 52*f0722ee7SPeter Tyser 53080c646dSJean-Christophe PLAGNIOL-VILLARD static int i2c_read_byte ( 54080c646dSJean-Christophe PLAGNIOL-VILLARD uint i2c_chan, /* I2C channel number: 0 - main, 1 - SDC SPD */ 55080c646dSJean-Christophe PLAGNIOL-VILLARD uchar chip_addr,/* I2C device address on the bus */ 56080c646dSJean-Christophe PLAGNIOL-VILLARD uint byte_addr, /* Byte address within I2C device */ 57080c646dSJean-Christophe PLAGNIOL-VILLARD uchar * buffer /* pointer to data buffer */ 58080c646dSJean-Christophe PLAGNIOL-VILLARD ) 59080c646dSJean-Christophe PLAGNIOL-VILLARD { 60080c646dSJean-Christophe PLAGNIOL-VILLARD u32 temp; 61080c646dSJean-Christophe PLAGNIOL-VILLARD u32 to_count = I2C_DELAY; 62080c646dSJean-Christophe PLAGNIOL-VILLARD u32 op_status = TSI108_I2C_TIMEOUT_ERR; 63080c646dSJean-Christophe PLAGNIOL-VILLARD u32 chan_offset = TSI108_I2C_OFFSET; 64080c646dSJean-Christophe PLAGNIOL-VILLARD 65080c646dSJean-Christophe PLAGNIOL-VILLARD DPRINT (("I2C read_byte() %d 0x%02x 0x%02x\n", 66080c646dSJean-Christophe PLAGNIOL-VILLARD i2c_chan, chip_addr, byte_addr)); 67080c646dSJean-Christophe PLAGNIOL-VILLARD 68080c646dSJean-Christophe PLAGNIOL-VILLARD if (0 != i2c_chan) 69080c646dSJean-Christophe PLAGNIOL-VILLARD chan_offset = TSI108_I2C_SDRAM_OFFSET; 70080c646dSJean-Christophe PLAGNIOL-VILLARD 71080c646dSJean-Christophe PLAGNIOL-VILLARD /* Check if I2C operation is in progress */ 726d0f6bcfSJean-Christophe PLAGNIOL-VILLARD temp = *(u32 *) (CONFIG_SYS_TSI108_CSR_BASE + chan_offset + I2C_CNTRL2); 73080c646dSJean-Christophe PLAGNIOL-VILLARD 74080c646dSJean-Christophe PLAGNIOL-VILLARD if (0 == (temp & (I2C_CNTRL2_RD_STATUS | I2C_CNTRL2_WR_STATUS | 75080c646dSJean-Christophe PLAGNIOL-VILLARD I2C_CNTRL2_START))) { 76080c646dSJean-Christophe PLAGNIOL-VILLARD /* Set device address and operation (read = 0) */ 77080c646dSJean-Christophe PLAGNIOL-VILLARD temp = (byte_addr << 16) | ((chip_addr & 0x07) << 8) | 78080c646dSJean-Christophe PLAGNIOL-VILLARD ((chip_addr >> 3) & 0x0F); 796d0f6bcfSJean-Christophe PLAGNIOL-VILLARD *(u32 *) (CONFIG_SYS_TSI108_CSR_BASE + chan_offset + I2C_CNTRL1) = 80080c646dSJean-Christophe PLAGNIOL-VILLARD temp; 81080c646dSJean-Christophe PLAGNIOL-VILLARD 82080c646dSJean-Christophe PLAGNIOL-VILLARD /* Issue the read command 83080c646dSJean-Christophe PLAGNIOL-VILLARD * (at this moment all other parameters are 0 84080c646dSJean-Christophe PLAGNIOL-VILLARD * (size = 1 byte, lane = 0) 85080c646dSJean-Christophe PLAGNIOL-VILLARD */ 86080c646dSJean-Christophe PLAGNIOL-VILLARD 876d0f6bcfSJean-Christophe PLAGNIOL-VILLARD *(u32 *) (CONFIG_SYS_TSI108_CSR_BASE + chan_offset + I2C_CNTRL2) = 88080c646dSJean-Christophe PLAGNIOL-VILLARD (I2C_CNTRL2_START); 89080c646dSJean-Christophe PLAGNIOL-VILLARD 90080c646dSJean-Christophe PLAGNIOL-VILLARD /* Wait until operation completed */ 91080c646dSJean-Christophe PLAGNIOL-VILLARD do { 92080c646dSJean-Christophe PLAGNIOL-VILLARD /* Read I2C operation status */ 936d0f6bcfSJean-Christophe PLAGNIOL-VILLARD temp = *(u32 *) (CONFIG_SYS_TSI108_CSR_BASE + chan_offset + I2C_CNTRL2); 94080c646dSJean-Christophe PLAGNIOL-VILLARD 95080c646dSJean-Christophe PLAGNIOL-VILLARD if (0 == (temp & (I2C_CNTRL2_RD_STATUS | I2C_CNTRL2_START))) { 96080c646dSJean-Christophe PLAGNIOL-VILLARD if (0 == (temp & 97080c646dSJean-Christophe PLAGNIOL-VILLARD (I2C_CNTRL2_I2C_CFGERR | 98080c646dSJean-Christophe PLAGNIOL-VILLARD I2C_CNTRL2_I2C_TO_ERR)) 99080c646dSJean-Christophe PLAGNIOL-VILLARD ) { 100080c646dSJean-Christophe PLAGNIOL-VILLARD op_status = TSI108_I2C_SUCCESS; 101080c646dSJean-Christophe PLAGNIOL-VILLARD 1026d0f6bcfSJean-Christophe PLAGNIOL-VILLARD temp = *(u32 *) (CONFIG_SYS_TSI108_CSR_BASE + 103080c646dSJean-Christophe PLAGNIOL-VILLARD chan_offset + 104080c646dSJean-Christophe PLAGNIOL-VILLARD I2C_RD_DATA); 105080c646dSJean-Christophe PLAGNIOL-VILLARD 106080c646dSJean-Christophe PLAGNIOL-VILLARD *buffer = (u8) (temp & 0xFF); 107080c646dSJean-Christophe PLAGNIOL-VILLARD } else { 108080c646dSJean-Christophe PLAGNIOL-VILLARD /* report HW error */ 109080c646dSJean-Christophe PLAGNIOL-VILLARD op_status = TSI108_I2C_IF_ERROR; 110080c646dSJean-Christophe PLAGNIOL-VILLARD 111080c646dSJean-Christophe PLAGNIOL-VILLARD DPRINT (("I2C HW error reported: 0x%02x\n", temp)); 112080c646dSJean-Christophe PLAGNIOL-VILLARD } 113080c646dSJean-Christophe PLAGNIOL-VILLARD 114080c646dSJean-Christophe PLAGNIOL-VILLARD break; 115080c646dSJean-Christophe PLAGNIOL-VILLARD } 116080c646dSJean-Christophe PLAGNIOL-VILLARD } while (to_count--); 117080c646dSJean-Christophe PLAGNIOL-VILLARD } else { 118080c646dSJean-Christophe PLAGNIOL-VILLARD op_status = TSI108_I2C_IF_BUSY; 119080c646dSJean-Christophe PLAGNIOL-VILLARD 120080c646dSJean-Christophe PLAGNIOL-VILLARD DPRINT (("I2C Transaction start failed: 0x%02x\n", temp)); 121080c646dSJean-Christophe PLAGNIOL-VILLARD } 122080c646dSJean-Christophe PLAGNIOL-VILLARD 123080c646dSJean-Christophe PLAGNIOL-VILLARD DPRINT (("I2C read_byte() status: 0x%02x\n", op_status)); 124080c646dSJean-Christophe PLAGNIOL-VILLARD return op_status; 125080c646dSJean-Christophe PLAGNIOL-VILLARD } 126080c646dSJean-Christophe PLAGNIOL-VILLARD 127080c646dSJean-Christophe PLAGNIOL-VILLARD /* 128080c646dSJean-Christophe PLAGNIOL-VILLARD * I2C Read interface as defined in "include/i2c.h" : 129080c646dSJean-Christophe PLAGNIOL-VILLARD * chip_addr: I2C chip address, range 0..127 130080c646dSJean-Christophe PLAGNIOL-VILLARD * (to read from SPD channel EEPROM use (0xD0 ... 0xD7) 131080c646dSJean-Christophe PLAGNIOL-VILLARD * NOTE: The bit 7 in the chip_addr serves as a channel select. 132080c646dSJean-Christophe PLAGNIOL-VILLARD * This hack is for enabling "isdram" command on Tsi108 boards 133080c646dSJean-Christophe PLAGNIOL-VILLARD * without changes to common code. Used for I2C reads only. 134080c646dSJean-Christophe PLAGNIOL-VILLARD * byte_addr: Memory or register address within the chip 135080c646dSJean-Christophe PLAGNIOL-VILLARD * alen: Number of bytes to use for addr (typically 1, 2 for larger 136080c646dSJean-Christophe PLAGNIOL-VILLARD * memories, 0 for register type devices with only one 137080c646dSJean-Christophe PLAGNIOL-VILLARD * register) 138080c646dSJean-Christophe PLAGNIOL-VILLARD * buffer: Pointer to destination buffer for data to be read 139080c646dSJean-Christophe PLAGNIOL-VILLARD * len: How many bytes to read 140080c646dSJean-Christophe PLAGNIOL-VILLARD * 141080c646dSJean-Christophe PLAGNIOL-VILLARD * Returns: 0 on success, not 0 on failure 142080c646dSJean-Christophe PLAGNIOL-VILLARD */ 143080c646dSJean-Christophe PLAGNIOL-VILLARD 144080c646dSJean-Christophe PLAGNIOL-VILLARD int i2c_read (uchar chip_addr, uint byte_addr, int alen, 145080c646dSJean-Christophe PLAGNIOL-VILLARD uchar * buffer, int len) 146080c646dSJean-Christophe PLAGNIOL-VILLARD { 147080c646dSJean-Christophe PLAGNIOL-VILLARD u32 op_status = TSI108_I2C_PARAM_ERR; 148080c646dSJean-Christophe PLAGNIOL-VILLARD u32 i2c_if = 0; 149080c646dSJean-Christophe PLAGNIOL-VILLARD 150080c646dSJean-Christophe PLAGNIOL-VILLARD /* Hack to support second (SPD) I2C controller (SPD EEPROM read only).*/ 151080c646dSJean-Christophe PLAGNIOL-VILLARD if (0xD0 == (chip_addr & ~0x07)) { 152080c646dSJean-Christophe PLAGNIOL-VILLARD i2c_if = 1; 153080c646dSJean-Christophe PLAGNIOL-VILLARD chip_addr &= 0x7F; 154080c646dSJean-Christophe PLAGNIOL-VILLARD } 155080c646dSJean-Christophe PLAGNIOL-VILLARD /* Check for valid I2C address */ 156080c646dSJean-Christophe PLAGNIOL-VILLARD if (chip_addr <= 0x7F && (byte_addr + len) <= (0x01 << (alen * 8))) { 157080c646dSJean-Christophe PLAGNIOL-VILLARD while (len--) { 158080c646dSJean-Christophe PLAGNIOL-VILLARD op_status = i2c_read_byte(i2c_if, chip_addr, byte_addr++, buffer++); 159080c646dSJean-Christophe PLAGNIOL-VILLARD 160080c646dSJean-Christophe PLAGNIOL-VILLARD if (TSI108_I2C_SUCCESS != op_status) { 161080c646dSJean-Christophe PLAGNIOL-VILLARD DPRINT (("I2C read_byte() failed: 0x%02x (%d left)\n", op_status, len)); 162080c646dSJean-Christophe PLAGNIOL-VILLARD 163080c646dSJean-Christophe PLAGNIOL-VILLARD break; 164080c646dSJean-Christophe PLAGNIOL-VILLARD } 165080c646dSJean-Christophe PLAGNIOL-VILLARD } 166080c646dSJean-Christophe PLAGNIOL-VILLARD } 167080c646dSJean-Christophe PLAGNIOL-VILLARD 168080c646dSJean-Christophe PLAGNIOL-VILLARD DPRINT (("I2C read() status: 0x%02x\n", op_status)); 169080c646dSJean-Christophe PLAGNIOL-VILLARD return op_status; 170080c646dSJean-Christophe PLAGNIOL-VILLARD } 171080c646dSJean-Christophe PLAGNIOL-VILLARD 172080c646dSJean-Christophe PLAGNIOL-VILLARD /* I2C write helper function */ 173080c646dSJean-Christophe PLAGNIOL-VILLARD 174080c646dSJean-Christophe PLAGNIOL-VILLARD static int i2c_write_byte (uchar chip_addr,/* I2C device address on the bus */ 175080c646dSJean-Christophe PLAGNIOL-VILLARD uint byte_addr, /* Byte address within I2C device */ 176080c646dSJean-Christophe PLAGNIOL-VILLARD uchar * buffer /* pointer to data buffer */ 177080c646dSJean-Christophe PLAGNIOL-VILLARD ) 178080c646dSJean-Christophe PLAGNIOL-VILLARD { 179080c646dSJean-Christophe PLAGNIOL-VILLARD u32 temp; 180080c646dSJean-Christophe PLAGNIOL-VILLARD u32 to_count = I2C_DELAY; 181080c646dSJean-Christophe PLAGNIOL-VILLARD u32 op_status = TSI108_I2C_TIMEOUT_ERR; 182080c646dSJean-Christophe PLAGNIOL-VILLARD 183080c646dSJean-Christophe PLAGNIOL-VILLARD /* Check if I2C operation is in progress */ 1846d0f6bcfSJean-Christophe PLAGNIOL-VILLARD temp = *(u32 *) (CONFIG_SYS_TSI108_CSR_BASE + TSI108_I2C_OFFSET + I2C_CNTRL2); 185080c646dSJean-Christophe PLAGNIOL-VILLARD 186080c646dSJean-Christophe PLAGNIOL-VILLARD if (0 == (temp & (I2C_CNTRL2_RD_STATUS | I2C_CNTRL2_WR_STATUS | I2C_CNTRL2_START))) { 187080c646dSJean-Christophe PLAGNIOL-VILLARD /* Place data into the I2C Tx Register */ 1886d0f6bcfSJean-Christophe PLAGNIOL-VILLARD *(u32 *) (CONFIG_SYS_TSI108_CSR_BASE + TSI108_I2C_OFFSET + 189080c646dSJean-Christophe PLAGNIOL-VILLARD I2C_TX_DATA) = (u32) * buffer; 190080c646dSJean-Christophe PLAGNIOL-VILLARD 191080c646dSJean-Christophe PLAGNIOL-VILLARD /* Set device address and operation */ 192080c646dSJean-Christophe PLAGNIOL-VILLARD temp = 193080c646dSJean-Christophe PLAGNIOL-VILLARD I2C_CNTRL1_I2CWRITE | (byte_addr << 16) | 194080c646dSJean-Christophe PLAGNIOL-VILLARD ((chip_addr & 0x07) << 8) | ((chip_addr >> 3) & 0x0F); 1956d0f6bcfSJean-Christophe PLAGNIOL-VILLARD *(u32 *) (CONFIG_SYS_TSI108_CSR_BASE + TSI108_I2C_OFFSET + 196080c646dSJean-Christophe PLAGNIOL-VILLARD I2C_CNTRL1) = temp; 197080c646dSJean-Christophe PLAGNIOL-VILLARD 198080c646dSJean-Christophe PLAGNIOL-VILLARD /* Issue the write command (at this moment all other parameters 199080c646dSJean-Christophe PLAGNIOL-VILLARD * are 0 (size = 1 byte, lane = 0) 200080c646dSJean-Christophe PLAGNIOL-VILLARD */ 201080c646dSJean-Christophe PLAGNIOL-VILLARD 2026d0f6bcfSJean-Christophe PLAGNIOL-VILLARD *(u32 *) (CONFIG_SYS_TSI108_CSR_BASE + TSI108_I2C_OFFSET + 203080c646dSJean-Christophe PLAGNIOL-VILLARD I2C_CNTRL2) = (I2C_CNTRL2_START); 204080c646dSJean-Christophe PLAGNIOL-VILLARD 205080c646dSJean-Christophe PLAGNIOL-VILLARD op_status = TSI108_I2C_TIMEOUT_ERR; 206080c646dSJean-Christophe PLAGNIOL-VILLARD 207080c646dSJean-Christophe PLAGNIOL-VILLARD /* Wait until operation completed */ 208080c646dSJean-Christophe PLAGNIOL-VILLARD do { 209080c646dSJean-Christophe PLAGNIOL-VILLARD /* Read I2C operation status */ 2106d0f6bcfSJean-Christophe PLAGNIOL-VILLARD temp = *(u32 *) (CONFIG_SYS_TSI108_CSR_BASE + TSI108_I2C_OFFSET + I2C_CNTRL2); 211080c646dSJean-Christophe PLAGNIOL-VILLARD 212080c646dSJean-Christophe PLAGNIOL-VILLARD if (0 == (temp & (I2C_CNTRL2_WR_STATUS | I2C_CNTRL2_START))) { 213080c646dSJean-Christophe PLAGNIOL-VILLARD if (0 == (temp & 214080c646dSJean-Christophe PLAGNIOL-VILLARD (I2C_CNTRL2_I2C_CFGERR | 215080c646dSJean-Christophe PLAGNIOL-VILLARD I2C_CNTRL2_I2C_TO_ERR))) { 216080c646dSJean-Christophe PLAGNIOL-VILLARD op_status = TSI108_I2C_SUCCESS; 217080c646dSJean-Christophe PLAGNIOL-VILLARD } else { 218080c646dSJean-Christophe PLAGNIOL-VILLARD /* report detected HW error */ 219080c646dSJean-Christophe PLAGNIOL-VILLARD op_status = TSI108_I2C_IF_ERROR; 220080c646dSJean-Christophe PLAGNIOL-VILLARD 221080c646dSJean-Christophe PLAGNIOL-VILLARD DPRINT (("I2C HW error reported: 0x%02x\n", temp)); 222080c646dSJean-Christophe PLAGNIOL-VILLARD } 223080c646dSJean-Christophe PLAGNIOL-VILLARD 224080c646dSJean-Christophe PLAGNIOL-VILLARD break; 225080c646dSJean-Christophe PLAGNIOL-VILLARD } 226080c646dSJean-Christophe PLAGNIOL-VILLARD 227080c646dSJean-Christophe PLAGNIOL-VILLARD } while (to_count--); 228080c646dSJean-Christophe PLAGNIOL-VILLARD } else { 229080c646dSJean-Christophe PLAGNIOL-VILLARD op_status = TSI108_I2C_IF_BUSY; 230080c646dSJean-Christophe PLAGNIOL-VILLARD 231080c646dSJean-Christophe PLAGNIOL-VILLARD DPRINT (("I2C Transaction start failed: 0x%02x\n", temp)); 232080c646dSJean-Christophe PLAGNIOL-VILLARD } 233080c646dSJean-Christophe PLAGNIOL-VILLARD 234080c646dSJean-Christophe PLAGNIOL-VILLARD return op_status; 235080c646dSJean-Christophe PLAGNIOL-VILLARD } 236080c646dSJean-Christophe PLAGNIOL-VILLARD 237080c646dSJean-Christophe PLAGNIOL-VILLARD /* 238080c646dSJean-Christophe PLAGNIOL-VILLARD * I2C Write interface as defined in "include/i2c.h" : 239080c646dSJean-Christophe PLAGNIOL-VILLARD * chip_addr: I2C chip address, range 0..127 240080c646dSJean-Christophe PLAGNIOL-VILLARD * byte_addr: Memory or register address within the chip 241080c646dSJean-Christophe PLAGNIOL-VILLARD * alen: Number of bytes to use for addr (typically 1, 2 for larger 242080c646dSJean-Christophe PLAGNIOL-VILLARD * memories, 0 for register type devices with only one 243080c646dSJean-Christophe PLAGNIOL-VILLARD * register) 244080c646dSJean-Christophe PLAGNIOL-VILLARD * buffer: Pointer to data to be written 245080c646dSJean-Christophe PLAGNIOL-VILLARD * len: How many bytes to write 246080c646dSJean-Christophe PLAGNIOL-VILLARD * 247080c646dSJean-Christophe PLAGNIOL-VILLARD * Returns: 0 on success, not 0 on failure 248080c646dSJean-Christophe PLAGNIOL-VILLARD */ 249080c646dSJean-Christophe PLAGNIOL-VILLARD 250080c646dSJean-Christophe PLAGNIOL-VILLARD int i2c_write (uchar chip_addr, uint byte_addr, int alen, uchar * buffer, 251080c646dSJean-Christophe PLAGNIOL-VILLARD int len) 252080c646dSJean-Christophe PLAGNIOL-VILLARD { 253080c646dSJean-Christophe PLAGNIOL-VILLARD u32 op_status = TSI108_I2C_PARAM_ERR; 254080c646dSJean-Christophe PLAGNIOL-VILLARD 255080c646dSJean-Christophe PLAGNIOL-VILLARD /* Check for valid I2C address */ 256080c646dSJean-Christophe PLAGNIOL-VILLARD if (chip_addr <= 0x7F && (byte_addr + len) <= (0x01 << (alen * 8))) { 257080c646dSJean-Christophe PLAGNIOL-VILLARD while (len--) { 258080c646dSJean-Christophe PLAGNIOL-VILLARD op_status = 259080c646dSJean-Christophe PLAGNIOL-VILLARD i2c_write_byte (chip_addr, byte_addr++, buffer++); 260080c646dSJean-Christophe PLAGNIOL-VILLARD 261080c646dSJean-Christophe PLAGNIOL-VILLARD if (TSI108_I2C_SUCCESS != op_status) { 262080c646dSJean-Christophe PLAGNIOL-VILLARD DPRINT (("I2C write_byte() failed: 0x%02x (%d left)\n", op_status, len)); 263080c646dSJean-Christophe PLAGNIOL-VILLARD 264080c646dSJean-Christophe PLAGNIOL-VILLARD break; 265080c646dSJean-Christophe PLAGNIOL-VILLARD } 266080c646dSJean-Christophe PLAGNIOL-VILLARD } 267080c646dSJean-Christophe PLAGNIOL-VILLARD } 268080c646dSJean-Christophe PLAGNIOL-VILLARD 269080c646dSJean-Christophe PLAGNIOL-VILLARD return op_status; 270080c646dSJean-Christophe PLAGNIOL-VILLARD } 271080c646dSJean-Christophe PLAGNIOL-VILLARD 272080c646dSJean-Christophe PLAGNIOL-VILLARD /* 273080c646dSJean-Christophe PLAGNIOL-VILLARD * I2C interface function as defined in "include/i2c.h". 274080c646dSJean-Christophe PLAGNIOL-VILLARD * Probe the given I2C chip address by reading single byte from offset 0. 275080c646dSJean-Christophe PLAGNIOL-VILLARD * Returns 0 if a chip responded, not 0 on failure. 276080c646dSJean-Christophe PLAGNIOL-VILLARD */ 277080c646dSJean-Christophe PLAGNIOL-VILLARD 278080c646dSJean-Christophe PLAGNIOL-VILLARD int i2c_probe (uchar chip) 279080c646dSJean-Christophe PLAGNIOL-VILLARD { 280080c646dSJean-Christophe PLAGNIOL-VILLARD u32 tmp; 281080c646dSJean-Christophe PLAGNIOL-VILLARD 282080c646dSJean-Christophe PLAGNIOL-VILLARD /* 283080c646dSJean-Christophe PLAGNIOL-VILLARD * Try to read the first location of the chip. 284080c646dSJean-Christophe PLAGNIOL-VILLARD * The Tsi108 HW doesn't support sending just the chip address 285080c646dSJean-Christophe PLAGNIOL-VILLARD * and checkong for an <ACK> back. 286080c646dSJean-Christophe PLAGNIOL-VILLARD */ 287080c646dSJean-Christophe PLAGNIOL-VILLARD return i2c_read (chip, 0, 1, (uchar *)&tmp, 1); 288080c646dSJean-Christophe PLAGNIOL-VILLARD } 289080c646dSJean-Christophe PLAGNIOL-VILLARD 290080c646dSJean-Christophe PLAGNIOL-VILLARD #endif 291