diff options
| author | Stefan Roese <sr@denx.de> | 2007-02-20 10:27:08 +0100 | 
|---|---|---|
| committer | Stefan Roese <sr@denx.de> | 2007-02-20 10:27:08 +0100 | 
| commit | 79b2d0bb2eae09602448f7a7cb56530d2f31e6c6 (patch) | |
| tree | ec226ccf8314e37981f946df4391446a6ff9dc11 | |
| parent | 7372ca68227930d03cffa548310524cad5b96733 (diff) | |
| download | olio-uboot-2014.01-79b2d0bb2eae09602448f7a7cb56530d2f31e6c6.tar.xz olio-uboot-2014.01-79b2d0bb2eae09602448f7a7cb56530d2f31e6c6.zip | |
[PATCH] PPC4xx: Add support for multiple I2C busses
This patch adds support for multiple I2C busses on the PPC4xx
platforms. Define CONFIG_I2C_MULTI_BUS in the board config file
to make use of this feature.
It also merges the 405 and 440 i2c header files into one common
file 4xx_i2c.h.
Also the 4xx i2c reset procedure is reworked since I experienced
some problems with the first access on the 440SPe Katmai board.
Signed-off-by: Stefan Roese <sr@denx.de>
| -rw-r--r-- | board/cray/L1/L1.c | 2 | ||||
| -rw-r--r-- | board/esd/du405/du405.c | 2 | ||||
| -rw-r--r-- | board/mpl/common/memtst.c | 2 | ||||
| -rw-r--r-- | board/mpl/mip405/mip405.c | 2 | ||||
| -rw-r--r-- | board/sandburst/common/ppc440gx_i2c.c | 7 | ||||
| -rw-r--r-- | board/sandburst/common/ppc440gx_i2c.h | 6 | ||||
| -rw-r--r-- | cpu/ppc4xx/i2c.c | 454 | ||||
| -rw-r--r-- | include/405gp_i2c.h | 64 | ||||
| -rw-r--r-- | include/440_i2c.h | 71 | ||||
| -rw-r--r-- | include/4xx_i2c.h | 122 | ||||
| -rw-r--r-- | include/i2c.h | 10 | 
11 files changed, 381 insertions, 361 deletions
| diff --git a/board/cray/L1/L1.c b/board/cray/L1/L1.c index a7114eb07..a0fac7fe5 100644 --- a/board/cray/L1/L1.c +++ b/board/cray/L1/L1.c @@ -23,7 +23,7 @@  #include <common.h>  #include <asm/processor.h> -#include <405gp_i2c.h> +#include <4xx_i2c.h>  #include <command.h>  #include <rtc.h>  #include <post.h> diff --git a/board/esd/du405/du405.c b/board/esd/du405/du405.c index a019ce421..69432138d 100644 --- a/board/esd/du405/du405.c +++ b/board/esd/du405/du405.c @@ -25,7 +25,7 @@  #include "du405.h"  #include <asm/processor.h>  #include <ppc4xx.h> -#include <405gp_i2c.h> +#include <4xx_i2c.h>  #include <command.h>  DECLARE_GLOBAL_DATA_PTR; diff --git a/board/mpl/common/memtst.c b/board/mpl/common/memtst.c index ff1190ab2..1d28513d8 100644 --- a/board/mpl/common/memtst.c +++ b/board/mpl/common/memtst.c @@ -48,7 +48,7 @@ int testdram (void)  #include <common.h>  #include <asm/processor.h> -#include <405gp_i2c.h> +#include <4xx_i2c.h>  DECLARE_GLOBAL_DATA_PTR; diff --git a/board/mpl/mip405/mip405.c b/board/mpl/mip405/mip405.c index 34f328999..4dbf4926c 100644 --- a/board/mpl/mip405/mip405.c +++ b/board/mpl/mip405/mip405.c @@ -65,7 +65,7 @@  #include <common.h>  #include "mip405.h"  #include <asm/processor.h> -#include <405gp_i2c.h> +#include <4xx_i2c.h>  #include <miiphy.h>  #include "../common/common_util.h"  #include <i2c.h> diff --git a/board/sandburst/common/ppc440gx_i2c.c b/board/sandburst/common/ppc440gx_i2c.c index 859dd7afe..1e3dffb1e 100644 --- a/board/sandburst/common/ppc440gx_i2c.c +++ b/board/sandburst/common/ppc440gx_i2c.c @@ -27,13 +27,8 @@   */  #include <common.h>  #include <ppc4xx.h> -#if defined(CONFIG_440) -#   include <440_i2c.h> -#else -#   include <405gp_i2c.h> -#endif +#include <4xx_i2c.h>  #include <i2c.h> -#include <440_i2c.h>  #include <command.h>  #include "ppc440gx_i2c.h" diff --git a/board/sandburst/common/ppc440gx_i2c.h b/board/sandburst/common/ppc440gx_i2c.h index cd4fc8666..10000f5ba 100644 --- a/board/sandburst/common/ppc440gx_i2c.h +++ b/board/sandburst/common/ppc440gx_i2c.h @@ -27,11 +27,7 @@   */  #include <common.h>  #include <ppc4xx.h> -#if defined(CONFIG_440) -#   include <440_i2c.h> -#else -#   include <405gp_i2c.h> -#endif +#include <4xx_i2c.h>  #include <i2c.h>  #ifdef CONFIG_HARD_I2C diff --git a/cpu/ppc4xx/i2c.c b/cpu/ppc4xx/i2c.c index 7db1cd804..0b056a15d 100644 --- a/cpu/ppc4xx/i2c.c +++ b/cpu/ppc4xx/i2c.c @@ -1,91 +1,100 @@ -/*****************************************************************************/ -/* I2C Bus interface initialisation and I2C Commands                         */ -/* for PPC405GP		                                                     */ -/* Author : AS HARNOIS                                                       */ -/* Date   : 13.Dec.00                                                        */ -/*****************************************************************************/ +/* + * (C) Copyright 2007 + * Stefan Roese, DENX Software Engineering, sr@denx.de. + * + * based on work by Anne Sophie Harnois <anne-sophie.harnois@nextream.fr> + * + * (C) Copyright 2001 + * Bill Hunter,  Wave 7 Optics, williamhunter@mediaone.net + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */  #include <common.h>  #include <ppc4xx.h> -#if defined(CONFIG_440) -#   include <440_i2c.h> -#else -#   include <405gp_i2c.h> -#endif +#include <4xx_i2c.h>  #include <i2c.h> +#include <asm-ppc/io.h>  #ifdef CONFIG_HARD_I2C  DECLARE_GLOBAL_DATA_PTR; -#define IIC_OK		0 -#define IIC_NOK		1 -#define IIC_NOK_LA	2		/* Lost arbitration */ -#define IIC_NOK_ICT	3		/* Incomplete transfer */ -#define IIC_NOK_XFRA	4		/* Transfer aborted */ -#define IIC_NOK_DATA	5		/* No data in buffer */ -#define IIC_NOK_TOUT	6		/* Transfer timeout */ - -#define IIC_TIMEOUT 1			/* 1 seconde */ - +#if defined(CONFIG_I2C_MULTI_BUS) +/* Initialize the bus pointer to whatever one the SPD EEPROM is on. + * Default is bus 0.  This is necessary because the DDR initialization + * runs from ROM, and we can't switch buses because we can't modify + * the global variables. + */ +#ifdef CFG_SPD_BUS_NUM +static unsigned int i2c_bus_num __attribute__ ((section ("data"))) = CFG_SPD_BUS_NUM; +#else +static unsigned int i2c_bus_num __attribute__ ((section ("data"))) = 0; +#endif +#endif /* CONFIG_I2C_MULTI_BUS */ -static void _i2c_bus_reset (void) +static void _i2c_bus_reset(void)  { -	int i, status; +	int i; +	u8 dc;  	/* Reset status register */  	/* write 1 in SCMP and IRQA to clear these fields */ -	out8 (IIC_STS, 0x0A); +	out_8((u8 *)IIC_STS, 0x0A);  	/* write 1 in IRQP IRQD LA ICT XFRA to clear these fields */ -	out8 (IIC_EXTSTS, 0x8F); -	__asm__ volatile ("eieio"); +	out_8((u8 *)IIC_EXTSTS, 0x8F); -	/* -	 * Get current state, reset bus -	 * only if no transfers are pending. -	 */ -	i = 10; -	do { -		/* Get status */ -		status = in8 (IIC_STS); -		udelay (500);			/* 500us */ -		i--; -	} while ((status & IIC_STS_PT) && (i > 0)); -	/* Soft reset controller */ -	status = in8 (IIC_XTCNTLSS); -	out8 (IIC_XTCNTLSS, (status | IIC_XTCNTLSS_SRST)); -	__asm__ volatile ("eieio"); +    	/* Place chip in the reset state */ +	out_8((u8 *)IIC_XTCNTLSS, IIC_XTCNTLSS_SRST); -	/* make sure where in initial state, data hi, clock hi */ -	out8 (IIC_DIRECTCNTL, 0xC); -	for (i = 0; i < 10; i++) { -		if ((in8 (IIC_DIRECTCNTL) & 0x3) != 0x3) { -			/* clock until we get to known state */ -			out8 (IIC_DIRECTCNTL, 0x8);	/* clock lo */ -			udelay (100);		/* 100us */ -			out8 (IIC_DIRECTCNTL, 0xC);	/* clock hi */ -			udelay (100);		/* 100us */ -		} else { -			break; +	/* Check if bus is free */ +	dc = in_8((u8 *)IIC_DIRECTCNTL); +	if (!DIRCTNL_FREE(dc)){ +		/* Try to set bus free state */ +		out_8((u8 *)IIC_DIRECTCNTL, IIC_DIRCNTL_SDAC | IIC_DIRCNTL_SCC); + +		/* Wait until we regain bus control */ +		for (i = 0; i < 100; ++i) { +			dc = in_8((u8 *)IIC_DIRECTCNTL); +			if (DIRCTNL_FREE(dc)) +				break; + +			/* Toggle SCL line */ +			dc ^= IIC_DIRCNTL_SCC; +			out_8((u8 *)IIC_DIRECTCNTL, dc); +			udelay(10); +			dc ^= IIC_DIRCNTL_SCC; +			out_8((u8 *)IIC_DIRECTCNTL, dc);  		}  	} -	/* send start condition */ -	out8 (IIC_DIRECTCNTL, 0x4); -	udelay (1000);				/* 1ms */ -	/* send stop condition */ -	out8 (IIC_DIRECTCNTL, 0xC); -	udelay (1000);				/* 1ms */ -	/* Unreset controller */ -	out8 (IIC_XTCNTLSS, (status & ~IIC_XTCNTLSS_SRST)); -	udelay (1000);				/* 1ms */ + +	/* Remove reset */ +	out_8((u8 *)IIC_XTCNTLSS, 0);  } -void i2c_init (int speed, int slaveadd) +void i2c_init(int speed, int slaveadd)  {  	sys_info_t sysInfo;  	unsigned long freqOPB;  	int val, divisor; +	int bus;  #ifdef CFG_I2C_INIT_BOARD  	/* call board specific i2c bus reset routine before accessing the   */ @@ -94,101 +103,100 @@ void i2c_init (int speed, int slaveadd)  	i2c_init_board();  #endif -	/* Handle possible failed I2C state */ -	/* FIXME: put this into i2c_init_board()? */ -	_i2c_bus_reset (); +	for (bus = 0; bus < CFG_MAX_I2C_BUS; bus++) { +		I2C_SET_BUS(bus); -	/* clear lo master address */ -	out8 (IIC_LMADR, 0); +		/* Handle possible failed I2C state */ +		/* FIXME: put this into i2c_init_board()? */ +		_i2c_bus_reset(); -	/* clear hi master address */ -	out8 (IIC_HMADR, 0); +		/* clear lo master address */ +		out_8((u8 *)IIC_LMADR, 0); -	/* clear lo slave address */ -	out8 (IIC_LSADR, 0); +		/* clear hi master address */ +		out_8((u8 *)IIC_HMADR, 0); -	/* clear hi slave address */ -	out8 (IIC_HSADR, 0); +		/* clear lo slave address */ +		out_8((u8 *)IIC_LSADR, 0); -	/* Clock divide Register */ -	/* get OPB frequency */ -	get_sys_info (&sysInfo); -	freqOPB = sysInfo.freqPLB / sysInfo.pllOpbDiv; -	/* set divisor according to freqOPB */ -	divisor = (freqOPB - 1) / 10000000; -	if (divisor == 0) -		divisor = 1; -	out8 (IIC_CLKDIV, divisor); +		/* clear hi slave address */ +		out_8((u8 *)IIC_HSADR, 0); -	/* no interrupts */ -	out8 (IIC_INTRMSK, 0); +		/* Clock divide Register */ +		/* get OPB frequency */ +		get_sys_info(&sysInfo); +		freqOPB = sysInfo.freqPLB / sysInfo.pllOpbDiv; +		/* set divisor according to freqOPB */ +		divisor = (freqOPB - 1) / 10000000; +		if (divisor == 0) +			divisor = 1; +		out_8((u8 *)IIC_CLKDIV, divisor); -	/* clear transfer count */ -	out8 (IIC_XFRCNT, 0); +		/* no interrupts */ +		out_8((u8 *)IIC_INTRMSK, 0); -	/* clear extended control & stat */ -	/* write 1 in SRC SRS SWC SWS to clear these fields */ -	out8 (IIC_XTCNTLSS, 0xF0); +		/* clear transfer count */ +		out_8((u8 *)IIC_XFRCNT, 0); -	/* Mode Control Register -	   Flush Slave/Master data buffer */ -	out8 (IIC_MDCNTL, IIC_MDCNTL_FSDB | IIC_MDCNTL_FMDB); -	__asm__ volatile ("eieio"); +		/* clear extended control & stat */ +		/* write 1 in SRC SRS SWC SWS to clear these fields */ +		out_8((u8 *)IIC_XTCNTLSS, 0xF0); +		/* Mode Control Register +		   Flush Slave/Master data buffer */ +		out_8((u8 *)IIC_MDCNTL, IIC_MDCNTL_FSDB | IIC_MDCNTL_FMDB); -	val = in8(IIC_MDCNTL); -	__asm__ volatile ("eieio"); +		val = in_8((u8 *)IIC_MDCNTL); -	/* 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; -	} -	out8 (IIC_MDCNTL, val); +		val |= IIC_MDCNTL_EUBS|IIC_MDCNTL_HSCL; +		if (speed >= 400000) +			val |= IIC_MDCNTL_FSM; +		out_8((u8 *)IIC_MDCNTL, val); -	/* clear control reg */ -	out8 (IIC_CNTL, 0x00); -	__asm__ volatile ("eieio"); +		/* clear control reg */ +		out_8((u8 *)IIC_CNTL, 0x00); +	} +	/* set to SPD bus as default bus upon powerup */ +	I2C_SET_BUS(CFG_SPD_BUS_NUM);  }  /* -  This code tries to use the features of the 405GP i2c -  controller. It will transfer up to 4 bytes in one pass -  on the loop. It only does out8(lbz) to the buffer when it -  is possible to do out16(lhz) transfers. - -  cmd_type is 0 for write 1 for read. - -  addr_len can take any value from 0-255, it is only limited -  by the char, we could make it larger if needed. If it is -  0 we skip the address write cycle. - -  Typical case is a Write of an addr followd by a Read. The -  IBM FAQ does not cover this. On the last byte of the write -  we don't set the creg CHT bit, and on the first bytes of the -  read we set the RPST bit. - -  It does not support address only transfers, there must be -  a data part. If you want to write the address yourself, put -  it in the data pointer. - -  It does not support transfer to/from address 0. - -  It does not check XFRCNT. -*/ -static -int i2c_transfer(unsigned char cmd_type, -		 unsigned char chip, -		 unsigned char addr[], -		 unsigned char addr_len, -		 unsigned char data[], -		 unsigned short data_len ) + * This code tries to use the features of the 405GP i2c + * controller. It will transfer up to 4 bytes in one pass + * on the loop. It only does out_8((u8 *)lbz) to the buffer when it + * is possible to do out16(lhz) transfers. + * + * cmd_type is 0 for write 1 for read. + * + * addr_len can take any value from 0-255, it is only limited + * by the char, we could make it larger if needed. If it is + * 0 we skip the address write cycle. + * + * Typical case is a Write of an addr followd by a Read. The + * IBM FAQ does not cover this. On the last byte of the write + * we don't set the creg CHT bit, and on the first bytes of the + * read we set the RPST bit. + * + * It does not support address only transfers, there must be + * a data part. If you want to write the address yourself, put + * it in the data pointer. + * + * It does not support transfer to/from address 0. + * + * It does not check XFRCNT. + */ +static int i2c_transfer(unsigned char cmd_type, +			unsigned char chip, +			unsigned char addr[], +			unsigned char addr_len, +			unsigned char data[], +			unsigned short data_len)  {  	unsigned char* ptr;  	int reading; @@ -198,97 +206,88 @@ int i2c_transfer(unsigned char cmd_type,  	int i;  	uchar creg; -	if( data == 0 || data_len == 0 ){ -		/*Don't support data transfer of no length or to address 0*/ +	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 ){ +	if (addr && addr_len) {  		ptr = addr;  		cnt = addr_len;  		reading = 0; -	}else{ +	} else {  		ptr = data;  		cnt = data_len;  		reading = cmd_type;  	} -	/*Clear Stop Complete Bit*/ -	out8(IIC_STS,IIC_STS_SCMP); +	/* Clear Stop Complete Bit */ +	out_8((u8 *)IIC_STS, IIC_STS_SCMP);  	/* Check init */ -	i=10; +	i = 10;  	do {  		/* Get status */ -		status = in8(IIC_STS); -		__asm__ volatile("eieio"); +		status = in_8((u8 *)IIC_STS);  		i--; -	} while ((status & IIC_STS_PT) && (i>0)); +	} 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*/ +	/* flush the Master/Slave Databuffers */ +	out_8((u8 *)IIC_MDCNTL, ((in_8((u8 *)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"); +	out_8((u8 *)IIC_HMADR, 0); +	out_8((u8 *)IIC_LMADR, chip);  	tran = 0;  	result = IIC_OK;  	creg = 0; -	while ( tran != cnt && (result == IIC_OK)) { +	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 -		*/ +		 * 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) ) +		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++) { +		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"); +				out_8((u8 *)IIC_MDBUF, ptr[tran+j]); +		out_8((u8 *)IIC_CNTL, creg);  		/* 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; +		 * 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); +			status = in_8((u8 *)IIC_STS); +			udelay(10);  			i--; -		} while ((status & IIC_STS_PT) && !(status & IIC_STS_ERR) -			 && (i>0)); +		} while ((status & IIC_STS_PT) && !(status & IIC_STS_ERR) && (i > 0));  		if (status & IIC_STS_ERR) {  			result = IIC_NOK; -			status = in8 (IIC_EXTSTS); +			status = in_8((u8 *)IIC_EXTSTS);  			/* Lost arbitration? */  			if (status & IIC_EXTSTS_LA)  				result = IIC_NOK_LA; @@ -306,34 +305,32 @@ int i2c_transfer(unsigned char cmd_type,  			/* 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"); -				} +				 * 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] = in_8((u8 *)IIC_MDBUF);  			} else  				result = IIC_NOK_DATA;  		}  		creg = 0; -		tran+=bc; -		if( ptr == addr && tran == cnt ) { +		tran += bc; +		if (ptr == addr && tran == cnt) {  			ptr = data;  			cnt = data_len;  			tran = 0;  			reading = cmd_type; -			if( reading ) +			if (reading)  				creg = IIC_CNTL_RPST;  		}  	}  	return (result);  } -int i2c_probe (uchar chip) +int i2c_probe(uchar chip)  {  	uchar buf[1]; @@ -344,21 +341,21 @@ int i2c_probe (uchar chip)  	 * 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); +	return (i2c_transfer(1, chip << 1, 0,0, buf, 1) != 0);  } -int i2c_read (uchar chip, uint addr, int alen, uchar * buffer, int len) +int i2c_read(uchar chip, uint addr, int alen, uchar * buffer, int len)  {  	uchar xaddr[4];  	int ret; -	if ( alen > 4 ) { +	if (alen > 4) {  		printf ("I2C read: addr len %d not supported\n", alen);  		return 1;  	} -	if ( alen > 0 ) { +	if (alen > 0) {  		xaddr[0] = (addr >> 24) & 0xFF;  		xaddr[1] = (addr >> 16) & 0xFF;  		xaddr[2] = (addr >> 8) & 0xFF; @@ -378,10 +375,10 @@ int i2c_read (uchar chip, uint addr, int alen, uchar * buffer, int len)  	 * still be one byte because the extra address bits are  	 * hidden in the chip address.  	 */ -	if( alen > 0 ) +	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) { +	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; @@ -389,16 +386,17 @@ int i2c_read (uchar chip, uint addr, int alen, uchar * buffer, int len)  	return 0;  } -int i2c_write (uchar chip, uint addr, int alen, uchar * buffer, int len) +int i2c_write(uchar chip, uint addr, int alen, uchar * buffer, int len)  {  	uchar xaddr[4]; -	if ( alen > 4 ) { +	if (alen > 4) {  		printf ("I2C write: addr len %d not supported\n", alen);  		return 1;  	} -	if ( alen > 0 ) { + +	if (alen > 0) {  		xaddr[0] = (addr >> 24) & 0xFF;  		xaddr[1] = (addr >> 16) & 0xFF;  		xaddr[2] = (addr >> 8) & 0xFF; @@ -417,11 +415,11 @@ int i2c_write (uchar chip, uint addr, int alen, uchar * buffer, int len)  	 * still be one byte because the extra address bits are  	 * hidden in the chip address.  	 */ -	if( alen > 0 ) +	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);  }  /*----------------------------------------------------------------------- @@ -433,7 +431,7 @@ uchar i2c_reg_read(uchar i2c_addr, uchar reg)  	i2c_read(i2c_addr, reg, 1, &buf, 1); -	return(buf); +	return (buf);  }  /*----------------------------------------------------------------------- @@ -443,4 +441,38 @@ void i2c_reg_write(uchar i2c_addr, uchar reg, uchar val)  {  	i2c_write(i2c_addr, reg, 1, &val, 1);  } + +#if defined(CONFIG_I2C_MULTI_BUS) +/* + * Functions for multiple I2C bus handling + */ +unsigned int i2c_get_bus_num(void) +{ +	return i2c_bus_num; +} + +int i2c_set_bus_num(unsigned int bus) +{ +	if (bus >= CFG_MAX_I2C_BUS) +		return -1; + +	i2c_bus_num = bus; + +	return 0; +} + +/* TODO: add 100/400k switching */ +unsigned int i2c_get_bus_speed(void) +{ +	return CFG_I2C_SPEED; +} + +int i2c_set_bus_speed(unsigned int speed) +{ +	if (speed != CFG_I2C_SPEED) +		return -1; + +	return 0; +} +#endif	/* CONFIG_I2C_MULTI_BUS */  #endif	/* CONFIG_HARD_I2C */ diff --git a/include/405gp_i2c.h b/include/405gp_i2c.h deleted file mode 100644 index 5a9a49753..000000000 --- a/include/405gp_i2c.h +++ /dev/null @@ -1,64 +0,0 @@ -#ifndef _405gp_i2c_h_ -#define _405gp_i2c_h_ - -#define	   I2C_REGISTERS_BASE_ADDRESS 0xEF600500 -#define    IIC_MDBUF	(I2C_REGISTERS_BASE_ADDRESS+IICMDBUF) -#define    IIC_SDBUF	(I2C_REGISTERS_BASE_ADDRESS+IICSDBUF) -#define    IIC_LMADR	(I2C_REGISTERS_BASE_ADDRESS+IICLMADR) -#define    IIC_HMADR	(I2C_REGISTERS_BASE_ADDRESS+IICHMADR) -#define    IIC_CNTL	(I2C_REGISTERS_BASE_ADDRESS+IICCNTL) -#define    IIC_MDCNTL	(I2C_REGISTERS_BASE_ADDRESS+IICMDCNTL) -#define    IIC_STS	(I2C_REGISTERS_BASE_ADDRESS+IICSTS) -#define    IIC_EXTSTS	(I2C_REGISTERS_BASE_ADDRESS+IICEXTSTS) -#define    IIC_LSADR	(I2C_REGISTERS_BASE_ADDRESS+IICLSADR) -#define    IIC_HSADR	(I2C_REGISTERS_BASE_ADDRESS+IICHSADR) -#define    IIC_CLKDIV	(I2C_REGISTERS_BASE_ADDRESS+IICCLKDIV) -#define    IIC_INTRMSK	(I2C_REGISTERS_BASE_ADDRESS+IICINTRMSK) -#define    IIC_XFRCNT	(I2C_REGISTERS_BASE_ADDRESS+IICXFRCNT) -#define    IIC_XTCNTLSS	(I2C_REGISTERS_BASE_ADDRESS+IICXTCNTLSS) -#define    IIC_DIRECTCNTL (I2C_REGISTERS_BASE_ADDRESS+IICDIRECTCNTL) - -/* MDCNTL Register Bit definition */ -#define    IIC_MDCNTL_HSCL 0x01 -#define    IIC_MDCNTL_EUBS 0x02 -#define    IIC_MDCNTL_EINT 0x04 -#define    IIC_MDCNTL_ESM  0x08 -#define    IIC_MDCNTL_FSM  0x10 -#define    IIC_MDCNTL_EGC  0x20 -#define    IIC_MDCNTL_FMDB 0x40 -#define    IIC_MDCNTL_FSDB 0x80 - -/* CNTL Register Bit definition */ -#define    IIC_CNTL_PT     0x01 -#define    IIC_CNTL_READ   0x02 -#define    IIC_CNTL_CHT    0x04 -#define    IIC_CNTL_RPST   0x08 -/* bit 2/3 for Transfer count*/ -#define    IIC_CNTL_AMD    0x40 -#define    IIC_CNTL_HMT    0x80 - -/* STS Register Bit definition */ -#define    IIC_STS_PT	   0X01 -#define    IIC_STS_IRQA    0x02 -#define    IIC_STS_ERR	   0X04 -#define    IIC_STS_SCMP    0x08 -#define    IIC_STS_MDBF    0x10 -#define    IIC_STS_MDBS    0X20 -#define    IIC_STS_SLPR    0x40 -#define    IIC_STS_SSS     0x80 - -/* EXTSTS Register Bit definition */ -#define    IIC_EXTSTS_XFRA 0X01 -#define    IIC_EXTSTS_ICT  0X02 -#define    IIC_EXTSTS_LA   0X04 - -/* XTCNTLSS Register Bit definition */ -#define    IIC_XTCNTLSS_SRST  0x01 -#define    IIC_XTCNTLSS_EPI   0x02 -#define    IIC_XTCNTLSS_SDBF  0x04 -#define    IIC_XTCNTLSS_SBDD  0x08 -#define    IIC_XTCNTLSS_SWS   0x10 -#define    IIC_XTCNTLSS_SWC   0x20 -#define    IIC_XTCNTLSS_SRS   0x40 -#define    IIC_XTCNTLSS_SRC   0x80 -#endif diff --git a/include/440_i2c.h b/include/440_i2c.h deleted file mode 100644 index 0c2bf3627..000000000 --- a/include/440_i2c.h +++ /dev/null @@ -1,71 +0,0 @@ -#ifndef _440_i2c_h_ -#define _440_i2c_h_ - -#if defined(CONFIG_440EP) || defined(CONFIG_440GR) || \ -    defined(CONFIG_440EPX) || defined(CONFIG_440GRX) -#define    I2C_BASE_ADDR (CFG_PERIPHERAL_BASE + 0x00000700) -#else -#define    I2C_BASE_ADDR (CFG_PERIPHERAL_BASE + 0x00000400) -#endif /*CONFIG_440EP CONFIG_440GR*/ - -#define	   I2C_REGISTERS_BASE_ADDRESS I2C_BASE_ADDR -#define    IIC_MDBUF	(I2C_REGISTERS_BASE_ADDRESS+IICMDBUF) -#define    IIC_SDBUF	(I2C_REGISTERS_BASE_ADDRESS+IICSDBUF) -#define    IIC_LMADR	(I2C_REGISTERS_BASE_ADDRESS+IICLMADR) -#define    IIC_HMADR	(I2C_REGISTERS_BASE_ADDRESS+IICHMADR) -#define    IIC_CNTL	(I2C_REGISTERS_BASE_ADDRESS+IICCNTL) -#define    IIC_MDCNTL	(I2C_REGISTERS_BASE_ADDRESS+IICMDCNTL) -#define    IIC_STS	(I2C_REGISTERS_BASE_ADDRESS+IICSTS) -#define    IIC_EXTSTS	(I2C_REGISTERS_BASE_ADDRESS+IICEXTSTS) -#define    IIC_LSADR	(I2C_REGISTERS_BASE_ADDRESS+IICLSADR) -#define    IIC_HSADR	(I2C_REGISTERS_BASE_ADDRESS+IICHSADR) -#define    IIC_CLKDIV	(I2C_REGISTERS_BASE_ADDRESS+IICCLKDIV) -#define    IIC_INTRMSK	(I2C_REGISTERS_BASE_ADDRESS+IICINTRMSK) -#define    IIC_XFRCNT	(I2C_REGISTERS_BASE_ADDRESS+IICXFRCNT) -#define    IIC_XTCNTLSS	(I2C_REGISTERS_BASE_ADDRESS+IICXTCNTLSS) -#define    IIC_DIRECTCNTL (I2C_REGISTERS_BASE_ADDRESS+IICDIRECTCNTL) - -/* MDCNTL Register Bit definition */ -#define    IIC_MDCNTL_HSCL 0x01 -#define    IIC_MDCNTL_EUBS 0x02 -#define    IIC_MDCNTL_EINT 0x04 -#define    IIC_MDCNTL_ESM  0x08 -#define    IIC_MDCNTL_FSM  0x10 -#define    IIC_MDCNTL_EGC  0x20 -#define    IIC_MDCNTL_FMDB 0x40 -#define    IIC_MDCNTL_FSDB 0x80 - -/* CNTL Register Bit definition */ -#define    IIC_CNTL_PT     0x01 -#define    IIC_CNTL_READ   0x02 -#define    IIC_CNTL_CHT    0x04 -#define    IIC_CNTL_RPST   0x08 -/* bit 2/3 for Transfer count*/ -#define    IIC_CNTL_AMD    0x40 -#define    IIC_CNTL_HMT    0x80 - -/* STS Register Bit definition */ -#define    IIC_STS_PT	   0X01 -#define    IIC_STS_IRQA    0x02 -#define    IIC_STS_ERR	   0X04 -#define    IIC_STS_SCMP    0x08 -#define    IIC_STS_MDBF    0x10 -#define    IIC_STS_MDBS    0X20 -#define    IIC_STS_SLPR    0x40 -#define    IIC_STS_SSS     0x80 - -/* EXTSTS Register Bit definition */ -#define    IIC_EXTSTS_XFRA 0X01 -#define    IIC_EXTSTS_ICT  0X02 -#define    IIC_EXTSTS_LA   0X04 - -/* XTCNTLSS Register Bit definition */ -#define    IIC_XTCNTLSS_SRST  0x01 -#define    IIC_XTCNTLSS_EPI   0x02 -#define    IIC_XTCNTLSS_SDBF  0x04 -#define    IIC_XTCNTLSS_SBDD  0x08 -#define    IIC_XTCNTLSS_SWS   0x10 -#define    IIC_XTCNTLSS_SWC   0x20 -#define    IIC_XTCNTLSS_SRS   0x40 -#define    IIC_XTCNTLSS_SRC   0x80 -#endif diff --git a/include/4xx_i2c.h b/include/4xx_i2c.h new file mode 100644 index 000000000..66b799741 --- /dev/null +++ b/include/4xx_i2c.h @@ -0,0 +1,122 @@ +/* + * (C) Copyright 2007 + * Stefan Roese, DENX Software Engineering, sr@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _4xx_i2c_h_ +#define _4xx_i2c_h_ + +#define IIC_OK		0 +#define IIC_NOK		1 +#define IIC_NOK_LA	2		/* Lost arbitration */ +#define IIC_NOK_ICT	3		/* Incomplete transfer */ +#define IIC_NOK_XFRA	4		/* Transfer aborted */ +#define IIC_NOK_DATA	5		/* No data in buffer */ +#define IIC_NOK_TOUT	6		/* Transfer timeout */ + +#define IIC_TIMEOUT	1		/* 1 second */ + +#if defined(CONFIG_I2C_MULTI_BUS) +#define I2C_BUS_OFFS	(i2c_bus_num * 0x100) +#else +#define I2C_BUS_OFFS	(0x000) +#endif /* CONFIG_I2C_MULTI_BUS */ + +#if defined(CONFIG_440EP) || defined(CONFIG_440GR) || \ +    defined(CONFIG_440EPX) || defined(CONFIG_440GRX) +#define I2C_BASE_ADDR	(CFG_PERIPHERAL_BASE + 0x00000700 + I2C_BUS_OFFS) +#elif defined(CONFIG_440) +/* all remaining 440 variants */ +#define I2C_BASE_ADDR	(CFG_PERIPHERAL_BASE + 0x00000400 + I2C_BUS_OFFS) +#else +/* all 405 variants */ +#define I2C_BASE_ADDR	(0xEF600500 + I2C_BUS_OFFS) +#endif + +#define I2C_REGISTERS_BASE_ADDRESS I2C_BASE_ADDR +#define IIC_MDBUF	(I2C_REGISTERS_BASE_ADDRESS+IICMDBUF) +#define IIC_SDBUF	(I2C_REGISTERS_BASE_ADDRESS+IICSDBUF) +#define IIC_LMADR	(I2C_REGISTERS_BASE_ADDRESS+IICLMADR) +#define IIC_HMADR	(I2C_REGISTERS_BASE_ADDRESS+IICHMADR) +#define IIC_CNTL	(I2C_REGISTERS_BASE_ADDRESS+IICCNTL) +#define IIC_MDCNTL	(I2C_REGISTERS_BASE_ADDRESS+IICMDCNTL) +#define IIC_STS		(I2C_REGISTERS_BASE_ADDRESS+IICSTS) +#define IIC_EXTSTS	(I2C_REGISTERS_BASE_ADDRESS+IICEXTSTS) +#define IIC_LSADR	(I2C_REGISTERS_BASE_ADDRESS+IICLSADR) +#define IIC_HSADR	(I2C_REGISTERS_BASE_ADDRESS+IICHSADR) +#define IIC_CLKDIV	(I2C_REGISTERS_BASE_ADDRESS+IICCLKDIV) +#define IIC_INTRMSK	(I2C_REGISTERS_BASE_ADDRESS+IICINTRMSK) +#define IIC_XFRCNT	(I2C_REGISTERS_BASE_ADDRESS+IICXFRCNT) +#define IIC_XTCNTLSS	(I2C_REGISTERS_BASE_ADDRESS+IICXTCNTLSS) +#define IIC_DIRECTCNTL	(I2C_REGISTERS_BASE_ADDRESS+IICDIRECTCNTL) + +/* MDCNTL Register Bit definition */ +#define IIC_MDCNTL_HSCL		0x01 +#define IIC_MDCNTL_EUBS		0x02 +#define IIC_MDCNTL_EINT		0x04 +#define IIC_MDCNTL_ESM		0x08 +#define IIC_MDCNTL_FSM		0x10 +#define IIC_MDCNTL_EGC		0x20 +#define IIC_MDCNTL_FMDB		0x40 +#define IIC_MDCNTL_FSDB		0x80 + +/* CNTL Register Bit definition */ +#define IIC_CNTL_PT		0x01 +#define IIC_CNTL_READ		0x02 +#define IIC_CNTL_CHT		0x04 +#define IIC_CNTL_RPST		0x08 +/* bit 2/3 for Transfer count*/ +#define IIC_CNTL_AMD		0x40 +#define IIC_CNTL_HMT		0x80 + +/* STS Register Bit definition */ +#define IIC_STS_PT		0x01 +#define IIC_STS_IRQA		0x02 +#define IIC_STS_ERR		0x04 +#define IIC_STS_SCMP		0x08 +#define IIC_STS_MDBF		0x10 +#define IIC_STS_MDBS		0x20 +#define IIC_STS_SLPR		0x40 +#define IIC_STS_SSS		0x80 + +/* EXTSTS Register Bit definition */ +#define IIC_EXTSTS_XFRA		0x01 +#define IIC_EXTSTS_ICT		0x02 +#define IIC_EXTSTS_LA		0x04 + +/* XTCNTLSS Register Bit definition */ +#define IIC_XTCNTLSS_SRST	0x01 +#define IIC_XTCNTLSS_EPI	0x02 +#define IIC_XTCNTLSS_SDBF	0x04 +#define IIC_XTCNTLSS_SBDD	0x08 +#define IIC_XTCNTLSS_SWS	0x10 +#define IIC_XTCNTLSS_SWC	0x20 +#define IIC_XTCNTLSS_SRS	0x40 +#define IIC_XTCNTLSS_SRC	0x80 + +/* IICx_DIRECTCNTL register */ +#define IIC_DIRCNTL_SDAC	0x08 +#define IIC_DIRCNTL_SCC		0x04 +#define IIC_DIRCNTL_MSDA	0x02 +#define IIC_DIRCNTL_MSC		0x01 + +#define DIRCTNL_FREE(v)		(((v) & 0x0f) == 0x0f) +#endif diff --git a/include/i2c.h b/include/i2c.h index a8f729afe..54c6f9fbc 100644 --- a/include/i2c.h +++ b/include/i2c.h @@ -46,6 +46,16 @@   */  #define I2C_RXTX_LEN	128	/* maximum tx/rx buffer length */ +#if defined(CONFIG_I2C_MULTI_BUS) +#define CFG_MAX_I2C_BUS		2 +#define I2C_GET_BUS()		i2c_get_bus_num() +#define I2C_SET_BUS(a)		i2c_set_bus_num(a) +#else +#define CFG_MAX_I2C_BUS		1 +#define I2C_GET_BUS()		0 +#define I2C_SET_BUS(a) +#endif +  /*   * Initialization, must be called once on start up, may be called   * repeatedly to change the speed and slave addresses. |