X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;ds=inline;f=cpu%2Fppc4xx%2Fi2c.c;h=7db1cd8046b3c29d7fd5693faaa35208c0242072;hb=2b208f5308ae0c72a6840180e59ed1ab4f9b69fc;hp=7d8db9bf437980858cc91960188f69d9c44d206e;hpb=47cd00fa707af9de76408b69d3e911717dbbfab1;p=u-boot diff --git a/cpu/ppc4xx/i2c.c b/cpu/ppc4xx/i2c.c index 7d8db9bf43..7db1cd8046 100644 --- a/cpu/ppc4xx/i2c.c +++ b/cpu/ppc4xx/i2c.c @@ -16,6 +16,8 @@ #ifdef CONFIG_HARD_I2C +DECLARE_GLOBAL_DATA_PTR; + #define IIC_OK 0 #define IIC_NOK 1 #define IIC_NOK_LA 2 /* Lost arbitration */ @@ -85,7 +87,7 @@ void i2c_init (int speed, int slaveadd) unsigned long freqOPB; int val, divisor; -#ifdef CFG_I2C_INIT_BOARD +#ifdef CFG_I2C_INIT_BOARD /* call board specific i2c bus reset routine before accessing the */ /* environment, which might be in a chip on that bus. For details */ /* about this problem see doc/I2C_Edge_Conditions. */ @@ -134,19 +136,19 @@ void i2c_init (int speed, int slaveadd) __asm__ volatile ("eieio"); - val = in8(IIC_MDCNTL); - __asm__ volatile ("eieio"); + val = in8(IIC_MDCNTL); + __asm__ volatile ("eieio"); - /* Ignore General Call, slave transfers are ignored, - disable interrupts, exit unknown bus state, enable hold - SCL - 100kHz normaly or FastMode for 400kHz and above - */ + /* Ignore General Call, slave transfers are ignored, + disable interrupts, exit unknown bus state, enable hold + SCL + 100kHz normaly or FastMode for 400kHz and above + */ - val |= IIC_MDCNTL_EUBS|IIC_MDCNTL_HSCL; - if( speed >= 400000 ){ - val |= IIC_MDCNTL_FSM; - } + val |= IIC_MDCNTL_EUBS|IIC_MDCNTL_HSCL; + if( speed >= 400000 ){ + val |= IIC_MDCNTL_FSM; + } out8 (IIC_MDCNTL, val); /* clear control reg */ @@ -182,153 +184,153 @@ void i2c_init (int speed, int slaveadd) */ static int i2c_transfer(unsigned char cmd_type, - unsigned char chip, - unsigned char addr[], - unsigned char addr_len, - unsigned char data[], + unsigned char chip, + unsigned char addr[], + unsigned char addr_len, + unsigned char data[], unsigned short data_len ) { - unsigned char* ptr; - int reading; - int tran,cnt; - int result; - int status; - int i; - uchar creg; - - if( data == 0 || data_len == 0 ){ - /*Don't support data transfer of no length or to address 0*/ - printf( "i2c_transfer: bad call\n" ); - return IIC_NOK; - } - if( addr && addr_len ){ - ptr = addr; - cnt = addr_len; - reading = 0; - }else{ - ptr = data; - cnt = data_len; - reading = cmd_type; - } - - /*Clear Stop Complete Bit*/ - out8(IIC_STS,IIC_STS_SCMP); - /* Check init */ - i=10; - do { - /* Get status */ - status = in8(IIC_STS); - __asm__ volatile("eieio"); - i--; - } while ((status & IIC_STS_PT) && (i>0)); - - if (status & IIC_STS_PT) { - result = IIC_NOK_TOUT; - return(result); - } - /*flush the Master/Slave Databuffers*/ - out8(IIC_MDCNTL, ((in8(IIC_MDCNTL))|IIC_MDCNTL_FMDB|IIC_MDCNTL_FSDB)); - /*need to wait 4 OPB clocks? code below should take that long*/ - - /* 7-bit adressing */ - out8(IIC_HMADR,0); - out8(IIC_LMADR, chip); - __asm__ volatile("eieio"); - - tran = 0; - result = IIC_OK; - creg = 0; - - while ( tran != cnt && (result == IIC_OK)) { - int bc,j; - - /* Control register = - Normal transfer, 7-bits adressing, Transfer up to bc bytes, Normal start, - Transfer is a sequence of transfers - */ - creg |= IIC_CNTL_PT; - - bc = (cnt - tran) > 4 ? 4 : - cnt - tran; - creg |= (bc-1)<<4; - /* if the real cmd type is write continue trans*/ - if ( (!cmd_type && (ptr == addr)) || ((tran+bc) != cnt) ) - creg |= IIC_CNTL_CHT; - - if (reading) - creg |= IIC_CNTL_READ; - else { - for(j=0; j0)); + + if (status & IIC_STS_PT) { + result = IIC_NOK_TOUT; + return(result); + } + /*flush the Master/Slave Databuffers*/ + out8(IIC_MDCNTL, ((in8(IIC_MDCNTL))|IIC_MDCNTL_FMDB|IIC_MDCNTL_FSDB)); + /*need to wait 4 OPB clocks? code below should take that long*/ + + /* 7-bit adressing */ + out8(IIC_HMADR,0); + out8(IIC_LMADR, chip); + __asm__ volatile("eieio"); + + tran = 0; + result = IIC_OK; + creg = 0; + + while ( tran != cnt && (result == IIC_OK)) { + int bc,j; + + /* Control register = + Normal transfer, 7-bits adressing, Transfer up to bc bytes, Normal start, + Transfer is a sequence of transfers + */ + creg |= IIC_CNTL_PT; + + bc = (cnt - tran) > 4 ? 4 : + cnt - tran; + creg |= (bc-1)<<4; + /* if the real cmd type is write continue trans*/ + if ( (!cmd_type && (ptr == addr)) || ((tran+bc) != cnt) ) + creg |= IIC_CNTL_CHT; + + if (reading) + creg |= IIC_CNTL_READ; + else { + for(j=0; j0)); - if (status & IIC_STS_ERR) { - result = IIC_NOK; - status = in8 (IIC_EXTSTS); - /* Lost arbitration? */ - if (status & IIC_EXTSTS_LA) - result = IIC_NOK_LA; - /* Incomplete transfer? */ - if (status & IIC_EXTSTS_ICT) - result = IIC_NOK_ICT; - /* Transfer aborted? */ - if (status & IIC_EXTSTS_XFRA) - result = IIC_NOK_XFRA; - } else if ( status & IIC_STS_PT) { - result = IIC_NOK_TOUT; - } - /* Command is reading => get buffer */ - if ((reading) && (result == IIC_OK)) { - /* Are there data in buffer */ - if (status & IIC_STS_MDBS) { - /* - even if we have data we have to wait 4OPB clocks - for it to hit the front of the FIFO, after that - we can just read. We should check XFCNT here and - if the FIFO is full there is no need to wait. + if (status & IIC_STS_ERR) { + result = IIC_NOK; + status = in8 (IIC_EXTSTS); + /* Lost arbitration? */ + if (status & IIC_EXTSTS_LA) + result = IIC_NOK_LA; + /* Incomplete transfer? */ + if (status & IIC_EXTSTS_ICT) + result = IIC_NOK_ICT; + /* Transfer aborted? */ + if (status & IIC_EXTSTS_XFRA) + result = IIC_NOK_XFRA; + } else if ( status & IIC_STS_PT) { + result = IIC_NOK_TOUT; + } + /* Command is reading => get buffer */ + if ((reading) && (result == IIC_OK)) { + /* Are there data in buffer */ + if (status & IIC_STS_MDBS) { + /* + even if we have data we have to wait 4OPB clocks + for it to hit the front of the FIFO, after that + we can just read. We should check XFCNT here and + if the FIFO is full there is no need to wait. */ - udelay (1); - for(j=0;jed (i.e. there was a chip at that address which - * drove the data line low). - */ - return(i2c_transfer (1, chip << 1, 0,0, buf, 1) != 0); + /* + * What is needed is to send the chip address and verify that the + * address was ed (i.e. there was a chip at that address which + * drove the data line low). + */ + return(i2c_transfer (1, chip << 1, 0,0, buf, 1) != 0); } - int i2c_read (uchar chip, uint addr, int alen, uchar * buffer, int len) { - uchar xaddr[4]; - int ret; + uchar xaddr[4]; + int ret; if ( alen > 4 ) { printf ("I2C read: addr len %d not supported\n", alen); return 1; } - if ( alen > 0 ) { - xaddr[0] = (addr >> 24) & 0xFF; - xaddr[1] = (addr >> 16) & 0xFF; - xaddr[2] = (addr >> 8) & 0xFF; - xaddr[3] = addr & 0xFF; - } + if ( alen > 0 ) { + xaddr[0] = (addr >> 24) & 0xFF; + xaddr[1] = (addr >> 16) & 0xFF; + xaddr[2] = (addr >> 8) & 0xFF; + xaddr[3] = addr & 0xFF; + } #ifdef CFG_I2C_EEPROM_ADDR_OVERFLOW /* - * EEPROM chips that implement "address overflow" are ones - * like Catalyst 24WC04/08/16 which has 9/10/11 bits of - * address and the extra bits end up in the "chip address" - * bit slots. This makes a 24WC08 (1Kbyte) chip look like - * four 256 byte chips. + * EEPROM chips that implement "address overflow" are ones + * like Catalyst 24WC04/08/16 which has 9/10/11 bits of + * address and the extra bits end up in the "chip address" + * bit slots. This makes a 24WC08 (1Kbyte) chip look like + * four 256 byte chips. * - * Note that we consider the length of the address field to - * still be one byte because the extra address bits are - * hidden in the chip address. + * Note that we consider the length of the address field to + * still be one byte because the extra address bits are + * hidden in the chip address. */ - if( alen > 0 ) - chip |= ((addr >> (alen * 8)) & CFG_I2C_EEPROM_ADDR_OVERFLOW); + if( alen > 0 ) + chip |= ((addr >> (alen * 8)) & CFG_I2C_EEPROM_ADDR_OVERFLOW); #endif - if( (ret = i2c_transfer( 1, chip<<1, &xaddr[4-alen], alen, buffer, len )) != 0) { - printf( "I2c read: failed %d\n", ret); - return 1; - } - return 0; + if( (ret = i2c_transfer( 1, chip<<1, &xaddr[4-alen], alen, buffer, len )) != 0) { + if (gd->have_console) + printf( "I2c read: failed %d\n", ret); + return 1; + } + return 0; } int i2c_write (uchar chip, uint addr, int alen, uchar * buffer, int len) { - uchar xaddr[4]; + uchar xaddr[4]; if ( alen > 4 ) { printf ("I2C write: addr len %d not supported\n", alen); return 1; } - if ( alen > 0 ) { - xaddr[0] = (addr >> 24) & 0xFF; - xaddr[1] = (addr >> 16) & 0xFF; - xaddr[2] = (addr >> 8) & 0xFF; - xaddr[3] = addr & 0xFF; - } + if ( alen > 0 ) { + xaddr[0] = (addr >> 24) & 0xFF; + xaddr[1] = (addr >> 16) & 0xFF; + xaddr[2] = (addr >> 8) & 0xFF; + xaddr[3] = addr & 0xFF; + } #ifdef CFG_I2C_EEPROM_ADDR_OVERFLOW /* - * EEPROM chips that implement "address overflow" are ones - * like Catalyst 24WC04/08/16 which has 9/10/11 bits of - * address and the extra bits end up in the "chip address" - * bit slots. This makes a 24WC08 (1Kbyte) chip look like - * four 256 byte chips. + * EEPROM chips that implement "address overflow" are ones + * like Catalyst 24WC04/08/16 which has 9/10/11 bits of + * address and the extra bits end up in the "chip address" + * bit slots. This makes a 24WC08 (1Kbyte) chip look like + * four 256 byte chips. * - * Note that we consider the length of the address field to - * still be one byte because the extra address bits are - * hidden in the chip address. + * Note that we consider the length of the address field to + * still be one byte because the extra address bits are + * hidden in the chip address. */ - if( alen > 0 ) - chip |= ((addr >> (alen * 8)) & CFG_I2C_EEPROM_ADDR_OVERFLOW); + if( alen > 0 ) + chip |= ((addr >> (alen * 8)) & CFG_I2C_EEPROM_ADDR_OVERFLOW); #endif - return (i2c_transfer( 0, chip<<1, &xaddr[4-alen], alen, buffer, len ) != 0); + return (i2c_transfer( 0, chip<<1, &xaddr[4-alen], alen, buffer, len ) != 0); +} + +/*----------------------------------------------------------------------- + * Read a register + */ +uchar i2c_reg_read(uchar i2c_addr, uchar reg) +{ + uchar buf; + + i2c_read(i2c_addr, reg, 1, &buf, 1); + + return(buf); } +/*----------------------------------------------------------------------- + * Write a register + */ +void i2c_reg_write(uchar i2c_addr, uchar reg, uchar val) +{ + i2c_write(i2c_addr, reg, 1, &val, 1); +} #endif /* CONFIG_HARD_I2C */