From mboxrd@z Thu Jan 1 00:00:00 1970 From: Timur Tabi Date: Wed, 30 Aug 2006 16:39:58 -0500 Subject: [U-Boot-Users] [PATCH 2/2] Multi-bus I2C implementation of MPC834x In-Reply-To: <1156973751.13685.27.camel@saruman.qstreams.net> References: <1156973751.13685.27.camel@saruman.qstreams.net> Message-ID: <44F605AE.3010405@freescale.com> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de Ben Warren wrote: > Hello, > > Attached is a patch implementing multiple I2C buses on the MPC834x CPU > family and the MPC8349EMDS board in particular. Here's my patch which does the same thing. CHANGELOG: * The current support for dual I2C busses is specific to the MPC 8349. This patch makes it more generic. If two I2C busses are present (i.e. CFG_I2C2_OFFSET is defined), then the macro 'I2C' becomes a variable. Any code which needs to reference the I2C bus should make sure that 'I2C' points to the right bus before calling an i2c_* function. i2c_init() and do_i2c_probe() have been updated to automatically process both busses. And lastly, some hard-code constants have been replaced by macros. Signed-off-by: Timur Tabi --- board/mpc8349emds/pci.c | 2 +- common/cmd_i2c.c | 29 ++++++++++++++++++++++++----- cpu/mpc83xx/i2c.c | 35 +++++++++++++++++++++++++++++------ include/asm-ppc/i2c.h | 9 ++++----- 4 files changed, 58 insertions(+), 17 deletions(-) 4fa4904374e01e31ea155dbe340d72abd944617a diff --git a/board/mpc8349emds/pci.c b/board/mpc8349emds/pci.c index 63e4405..e91bfef 100644 --- a/board/mpc8349emds/pci.c +++ b/board/mpc8349emds/pci.c @@ -72,7 +72,7 @@ pib_init(void) /* * Assign PIB PMC slot to desired PCI bus */ - mpc8349_i2c = (i2c_t*)(CFG_IMMRBAR + CFG_I2C2_OFFSET); + I2C = (i2c_t*) (CFG_IMMRBAR + CFG_I2C2_OFFSET); i2c_init(CFG_I2C_SPEED, CFG_I2C_SLAVE); val8 = 0; diff --git a/common/cmd_i2c.c b/common/cmd_i2c.c index c543bb5..9f0980b 100644 --- a/common/cmd_i2c.c +++ b/common/cmd_i2c.c @@ -529,11 +529,7 @@ mod_i2c_mem(cmd_tbl_t *cmdtp, int incrfl return 0; } -/* - * Syntax: - * iprobe {addr}{.0, .1, .2} - */ -int do_i2c_probe (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +static void _do_i2c_probe(void) { int j; #if defined(CFG_I2C_NOPROBES) @@ -565,6 +561,29 @@ int do_i2c_probe (cmd_tbl_t *cmdtp, int printf(" %02X", i2c_no_probes[k] ); putc ('\n'); #endif +} + +/* + * Syntax: + * iprobe {addr}{.0, .1, .2} + */ +int do_i2c_probe(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ +#ifdef CFG_I2C2_OFFSET + +/* If we have two I2C busses, then we need to probe each one separately. + Note that if an I2C address is defined in i2c_no_probes[], we skip it + on both busses. +*/ + printf("I2C1 "); + I2C = (i2c_t *) (CFG_IMMRBAR + CFG_I2C_OFFSET); + _do_i2c_probe(); + + printf("I2C2 "); + I2C = (i2c_t *) (CFG_IMMRBAR + CFG_I2C2_OFFSET); +#endif + + _do_i2c_probe(); return 0; } diff --git a/cpu/mpc83xx/i2c.c b/cpu/mpc83xx/i2c.c index 70450f9..308a65d 100644 --- a/cpu/mpc83xx/i2c.c +++ b/cpu/mpc83xx/i2c.c @@ -41,21 +41,30 @@ #include #include -#if defined(CONFIG_MPC8349EMDS) || defined(CONFIG_TQM834X) -i2c_t * mpc8349_i2c = (i2c_t*)(CFG_IMMRBAR + CFG_I2C_OFFSET); +#ifdef CFG_I2C2_OFFSET +/* +To configure DDR RAM, we need to query the I2C bus. Since RAM hasn't +been initialized, U-Boot has not been copied yet to RAM. That means that +the global variable 'I2C' is located in flash, which means it can't be +modified. Therefore, 'I2C' needs to be initialized to the I2C bus that +DDR is on. + +CFG_I2C_DDR_OFFSET is the offset of the I2C bus that DDR is using. It +should be set to either CFG_I2C_OFFSET or CFG_I2C2_OFFSET. +*/ +volatile i2c_t *I2C = (i2c_t *) (CFG_IMMRBAR + CFG_I2C_DDR_OFFSET); #endif -void -i2c_init(int speed, int slaveadd) +static void _i2c_init(int slaveadd) { /* stop I2C controller */ writeb(0x00 , &I2C->cr); /* set clock */ - writeb(0x3f, &I2C->fdr); + writeb(IC2_FDR, &I2C->fdr); /* set default filter */ - writeb(0x10,&I2C->dfsrr); + writeb(I2C_CR_MTX, &I2C->dfsrr); /* write slave address */ writeb(slaveadd, &I2C->adr); @@ -67,6 +76,20 @@ i2c_init(int speed, int slaveadd) writeb(I2C_CR_MEN, &I2C->cr); } +void +i2c_init(int speed, int slaveadd) +{ +#ifdef CFG_I2C2_OFFSET + /* If it exists, initialize the 2nd I2C bus */ + I2C = (i2c_t *) (CFG_IMMRBAR + CFG_I2C_OFFSET); + _i2c_init(slaveadd); + + I2C = (i2c_t *) (CFG_IMMRBAR + CFG_I2C2_OFFSET); +#endif + _i2c_init(slaveadd); + +} + static __inline__ int i2c_wait4bus (void) { diff --git a/include/asm-ppc/i2c.h b/include/asm-ppc/i2c.h index 1680d3a..bd6a51d 100644 --- a/include/asm-ppc/i2c.h +++ b/include/asm-ppc/i2c.h @@ -87,14 +87,13 @@ typedef struct i2c #error CFG_I2C_OFFSET is not defined in /include/configs/${BOARD}.h #endif -#if defined(CONFIG_MPC8349EMDS) || defined(CONFIG_TQM834X) +#ifdef CFG_I2C2_OFFSET /* - * MPC8349 have two i2c bus + * If we have two I2C busses, then 'I2C' should be a variable, not a constant. */ -extern i2c_t * mpc8349_i2c; -#define I2C mpc8349_i2c +extern volatile i2c_t *I2C; #else -#define I2C ((i2c_t*)(CFG_IMMRBAR + CFG_I2C_OFFSET)) +#define I2C ((i2c_t*) (CFG_IMMRBAR + CFG_I2C_OFFSET)) #endif #define I2C_READ 1 -- 1.2.4 -- Timur Tabi Linux Kernel Developer @ Freescale