diff options
Diffstat (limited to 'cpu/ppc4xx/i2c.c')
| -rw-r--r-- | cpu/ppc4xx/i2c.c | 381 | 
1 files changed, 190 insertions, 191 deletions
| diff --git a/cpu/ppc4xx/i2c.c b/cpu/ppc4xx/i2c.c index 4bf0bbd99..099d30a05 100644 --- a/cpu/ppc4xx/i2c.c +++ b/cpu/ppc4xx/i2c.c @@ -85,7 +85,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 +134,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 +182,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; +	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; -        } +	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)); +	/*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*/ +	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"); +	/* 7-bit adressing */ +	out8(IIC_HMADR,0); +	out8(IIC_LMADR, chip); +	__asm__ volatile("eieio"); -        tran = 0; -        result = IIC_OK; -        creg = 0; +	tran = 0; +	result = IIC_OK; +	creg = 0; -        while ( tran != cnt && (result == IIC_OK)) { -                int  bc,j; +	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; +		/* 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; +		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; j<bc; j++) { -                                /* Set buffer */ -                                out8(IIC_MDBUF,ptr[tran+j]); -                                __asm__ volatile("eieio"); -                        } -                } -                out8(IIC_CNTL, creg ); -                __asm__ volatile("eieio"); +		if (reading) +			creg |= IIC_CNTL_READ; +		else { +			for(j=0; j<bc; j++) { +				/* Set buffer */ +				out8(IIC_MDBUF,ptr[tran+j]); +				__asm__ volatile("eieio"); +			} +		} +		out8(IIC_CNTL, creg ); +		__asm__ volatile("eieio"); -                /* Transfer is in progress -                   we have to wait for upto 5 bytes of data -                   1 byte chip address+r/w bit then bc bytes -                   of data. -                   udelay(10) is 1 bit time at 100khz -                   Doubled for slop. 20 is too small. +		/* Transfer is in progress +		   we have to wait for upto 5 bytes of data +		   1 byte chip address+r/w bit then bc bytes +		   of data. +		   udelay(10) is 1 bit time at 100khz +		   Doubled for slop. 20 is too small.  		*/ -                i=2*5*8; -                do { -                        /* Get status */ -                        status = in8(IIC_STS); -                        __asm__ volatile("eieio"); -                        udelay (10); -                        i--; -                } while ((status & IIC_STS_PT) && !(status & IIC_STS_ERR) +		i=2*5*8; +		do { +			/* Get status */ +			status = in8(IIC_STS); +			__asm__ volatile("eieio"); +			udelay (10); +			i--; +		} while ((status & IIC_STS_PT) && !(status & IIC_STS_ERR)  			 && (i>0)); -                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;j<bc;j++) { -                                        ptr[tran+j] = in8(IIC_MDBUF); -                                        __asm__ volatile("eieio"); -                                } -                        } else -                                result = IIC_NOK_DATA; -                } -                creg = 0; -                tran+=bc; -                if( ptr == addr && tran == cnt ) { -                        ptr = data; -                        cnt = data_len; -                        tran = 0; -                        reading = cmd_type; -                        if( reading ) -                                creg = IIC_CNTL_RPST; -                } -        } -        return (result); +				udelay (1); +				for(j=0;j<bc;j++) { +					ptr[tran+j] = in8(IIC_MDBUF); +					__asm__ volatile("eieio"); +				} +			} else +				result = IIC_NOK_DATA; +		} +		creg = 0; +		tran+=bc; +		if( ptr == addr && tran == cnt ) { +			ptr = data; +			cnt = data_len; +			tran = 0; +			reading = cmd_type; +			if( reading ) +				creg = IIC_CNTL_RPST; +		} +	} +	return (result);  }  int i2c_probe (uchar chip) @@ -337,89 +337,88 @@ int i2c_probe (uchar chip)  	buf[0] = 0; -        /* -         * What is needed is to send the chip address and verify that the -         * address was <ACK>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); +	/* +	 * What is needed is to send the chip address and verify that the +	 * address was <ACK>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) { +		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);  }  /*----------------------------------------------------------------------- |