From patchwork Wed Apr 24 11:43:45 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dirk Eibach X-Patchwork-Id: 239171 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id 623ED2C0114 for ; Wed, 24 Apr 2013 21:57:47 +1000 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id BB8EE4A130; Wed, 24 Apr 2013 13:57:45 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id QEpzH5Q5pHXt; Wed, 24 Apr 2013 13:57:45 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 337BE4A0C6; Wed, 24 Apr 2013 13:57:42 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id C1E8D4A113 for ; Wed, 24 Apr 2013 13:49:18 +0200 (CEST) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id EEfQdeCKLFks for ; Wed, 24 Apr 2013 13:49:15 +0200 (CEST) X-Greylist: delayed 303 seconds by postgrey-1.27 at theia; Wed, 24 Apr 2013 13:49:13 CEST X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from smtprelay02.ispgateway.de (smtprelay02.ispgateway.de [80.67.31.25]) by theia.denx.de (Postfix) with ESMTP id 605D84A110 for ; Wed, 24 Apr 2013 13:49:13 +0200 (CEST) Received: from [217.6.197.18] (helo=bob3.gd.local) by smtprelay02.ispgateway.de with esmtpa (Exim 4.68) (envelope-from ) id 1UUy7M-00058l-Mr; Wed, 24 Apr 2013 13:44:08 +0200 From: Dirk Eibach To: u-boot@lists.denx.de Date: Wed, 24 Apr 2013 13:43:45 +0200 Message-Id: <1366803825-17093-1-git-send-email-dirk.eibach@gdsys.cc> X-Mailer: git-send-email 1.7.2.5 In-Reply-To: <51762740.1060407@denx.de> References: <51762740.1060407@denx.de> X-Df-Sender: ZGlyay5laWJhY2hAZ2RzeXMuY2M= X-Mailman-Approved-At: Wed, 24 Apr 2013 13:57:40 +0200 Cc: Stefan Roese , Heiko Schocher Subject: [U-Boot] [RFC] i2c, ppc4xx_i2c: switch to new multibus/multiadapter support X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.11 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de Signed-off-by: Dirk Eibach Cc: Heiko Schocher Cc: Stefan Roese --- drivers/i2c/Makefile | 2 +- drivers/i2c/ppc4xx_i2c.c | 193 +++++++++++++++++++++++----------------------- 2 files changed, 97 insertions(+), 98 deletions(-) diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index 564d061..0298e3e 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile @@ -36,7 +36,6 @@ COBJS-$(CONFIG_DRIVER_OMAP1510_I2C) += omap1510_i2c.o COBJS-$(CONFIG_DRIVER_OMAP24XX_I2C) += omap24xx_i2c.o COBJS-$(CONFIG_DRIVER_OMAP34XX_I2C) += omap24xx_i2c.o COBJS-$(CONFIG_PCA9564_I2C) += pca9564_i2c.o -COBJS-$(CONFIG_PPC4XX_I2C) += ppc4xx_i2c.o COBJS-$(CONFIG_DRIVER_S3C24X0_I2C) += s3c24x0_i2c.o COBJS-$(CONFIG_S3C44B0_I2C) += s3c44b0_i2c.o COBJS-$(CONFIG_TSI108_I2C) += tsi108_i2c.o @@ -45,6 +44,7 @@ COBJS-$(CONFIG_SH_I2C) += sh_i2c.o COBJS-$(CONFIG_SH_SH7734_I2C) += sh_sh7734_i2c.o COBJS-$(CONFIG_SYS_I2C) += i2c_core.o COBJS-$(CONFIG_SYS_I2C_FSL) += fsl_i2c.o +COBJS-$(CONFIG_SYS_I2C_PPC4XX) += ppc4xx_i2c.o COBJS-$(CONFIG_SYS_I2C_SOFT) += soft_i2c.o COBJS-$(CONFIG_SYS_I2C_TEGRA) += tegra_i2c.o diff --git a/drivers/i2c/ppc4xx_i2c.c b/drivers/i2c/ppc4xx_i2c.c index 53fedd5..c924874 100644 --- a/drivers/i2c/ppc4xx_i2c.c +++ b/drivers/i2c/ppc4xx_i2c.c @@ -32,27 +32,29 @@ #include #include -#ifdef CONFIG_HARD_I2C - DECLARE_GLOBAL_DATA_PTR; -#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. - */ -#ifndef CONFIG_SYS_SPD_BUS_NUM -#define CONFIG_SYS_SPD_BUS_NUM 0 +static inline struct ppc4xx_i2c *ppc4xx_get_i2c(int hwadapnr) +{ + unsigned long base; + +#if defined(CONFIG_440EP) || defined(CONFIG_440GR) || \ + defined(CONFIG_440EPX) || defined(CONFIG_440GRX) || \ + defined(CONFIG_460EX) || defined(CONFIG_460GT) + base = CONFIG_SYS_PERIPHERAL_BASE + 0x00000700 + (hwadapnr * 0x100); +#elif defined(CONFIG_440) || defined(CONFIG_405EX) +/* all remaining 440 variants */ + base = CONFIG_SYS_PERIPHERAL_BASE + 0x00000400 + (hwadapnr * 0x100); +#else +/* all 405 variants */ + base = 0xEF600500 + (hwadapnr * 0x100); #endif -static unsigned int i2c_bus_num __attribute__ ((section (".data"))) = - CONFIG_SYS_SPD_BUS_NUM; -#endif /* CONFIG_I2C_MULTI_BUS */ + return (struct ppc4xx_i2c *)base; +} -static void _i2c_bus_reset(void) +static void _i2c_bus_reset(struct i2c_adapter *adap) { - struct ppc4xx_i2c *i2c = (struct ppc4xx_i2c *)I2C_BASE_ADDR; + struct ppc4xx_i2c *i2c = ppc4xx_get_i2c(adap->hwadapnr); int i; u8 dc; @@ -91,11 +93,10 @@ static void _i2c_bus_reset(void) out_8(&i2c->xtcntlss, 0); } -void i2c_init(int speed, int slaveaddr) +static void ppc4xx_i2c_init(struct i2c_adapter *adap, int speed, int slaveaddr) { - struct ppc4xx_i2c *i2c; + struct ppc4xx_i2c *i2c = ppc4xx_get_i2c(adap->hwadapnr); int val, divisor; - int bus; #ifdef CONFIG_SYS_I2C_INIT_BOARD /* @@ -106,67 +107,57 @@ void i2c_init(int speed, int slaveaddr) i2c_init_board(); #endif - for (bus = 0; bus < CONFIG_SYS_MAX_I2C_BUS; bus++) { - I2C_SET_BUS(bus); - - /* Set i2c pointer after calling I2C_SET_BUS() */ - i2c = (struct ppc4xx_i2c *)I2C_BASE_ADDR; - - /* Handle possible failed I2C state */ - /* FIXME: put this into i2c_init_board()? */ - _i2c_bus_reset(); + /* Handle possible failed I2C state */ + /* FIXME: put this into i2c_init_board()? */ + _i2c_bus_reset(adap); - /* clear lo master address */ - out_8(&i2c->lmadr, 0); + /* clear lo master address */ + out_8(&i2c->lmadr, 0); - /* clear hi master address */ - out_8(&i2c->hmadr, 0); - - /* clear lo slave address */ - out_8(&i2c->lsadr, 0); + /* clear hi master address */ + out_8(&i2c->hmadr, 0); - /* clear hi slave address */ - out_8(&i2c->hsadr, 0); + /* clear lo slave address */ + out_8(&i2c->lsadr, 0); - /* Clock divide Register */ - /* set divisor according to freq_opb */ - divisor = (get_OPB_freq() - 1) / 10000000; - if (divisor == 0) - divisor = 1; - out_8(&i2c->clkdiv, divisor); + /* clear hi slave address */ + out_8(&i2c->hsadr, 0); - /* no interrupts */ - out_8(&i2c->intrmsk, 0); + /* Clock divide Register */ + /* set divisor according to freq_opb */ + divisor = (get_OPB_freq() - 1) / 10000000; + if (divisor == 0) + divisor = 1; + out_8(&i2c->clkdiv, divisor); - /* clear transfer count */ - out_8(&i2c->xfrcnt, 0); + /* no interrupts */ + out_8(&i2c->intrmsk, 0); - /* clear extended control & stat */ - /* write 1 in SRC SRS SWC SWS to clear these fields */ - out_8(&i2c->xtcntlss, 0xF0); + /* clear transfer count */ + out_8(&i2c->xfrcnt, 0); - /* Mode Control Register - Flush Slave/Master data buffer */ - out_8(&i2c->mdcntl, IIC_MDCNTL_FSDB | IIC_MDCNTL_FMDB); + /* clear extended control & stat */ + /* write 1 in SRC SRS SWC SWS to clear these fields */ + out_8(&i2c->xtcntlss, 0xF0); - val = in_8(&i2c->mdcntl); + /* Mode Control Register + Flush Slave/Master data buffer */ + out_8(&i2c->mdcntl, IIC_MDCNTL_FSDB | IIC_MDCNTL_FMDB); - /* 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 = in_8(&i2c->mdcntl); - val |= IIC_MDCNTL_EUBS | IIC_MDCNTL_HSCL; - if (speed >= 400000) - val |= IIC_MDCNTL_FSM; - out_8(&i2c->mdcntl, val); + /* Ignore General Call, slave transfers are ignored, + * disable interrupts, exit unknown bus state, enable hold + * SCL 100kHz normaly or FastMode for 400kHz and above + */ - /* clear control reg */ - out_8(&i2c->cntl, 0x00); - } + val |= IIC_MDCNTL_EUBS | IIC_MDCNTL_HSCL; + if (speed >= 400000) + val |= IIC_MDCNTL_FSM; + out_8(&i2c->mdcntl, val); - /* set to SPD bus as default bus upon powerup */ - I2C_SET_BUS(CONFIG_SYS_SPD_BUS_NUM); + /* clear control reg */ + out_8(&i2c->cntl, 0x00); } /* @@ -194,14 +185,15 @@ void i2c_init(int speed, int slaveaddr) * * It does not check XFRCNT. */ -static int i2c_transfer(unsigned char cmd_type, +static int _i2c_transfer(struct i2c_adapter *adap, + unsigned char cmd_type, unsigned char chip, unsigned char addr[], unsigned char addr_len, unsigned char data[], unsigned short data_len) { - struct ppc4xx_i2c *i2c = (struct ppc4xx_i2c *)I2C_BASE_ADDR; + struct ppc4xx_i2c *i2c = ppc4xx_get_i2c(adap->hwadapnr); u8 *ptr; int reading; int tran, cnt; @@ -345,7 +337,7 @@ static int i2c_transfer(unsigned char cmd_type, return result; } -int i2c_probe(uchar chip) +static int ppc4xx_i2c_probe(struct i2c_adapter *adap, uchar chip) { uchar buf[1]; @@ -356,11 +348,11 @@ int i2c_probe(uchar chip) * 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); + return (_i2c_transfer(adap, 1, chip << 1, 0, 0, buf, 1) != 0); } -static int ppc4xx_i2c_transfer(uchar chip, uint addr, int alen, uchar *buffer, - int len, int read) +static int ppc4xx_i2c_transfer(struct i2c_adapter *adap, uchar chip, uint addr, + int alen, uchar *buffer, int len, int read) { uchar xaddr[4]; int ret; @@ -394,43 +386,50 @@ static int ppc4xx_i2c_transfer(uchar chip, uint addr, int alen, uchar *buffer, chip |= ((addr >> (alen * 8)) & CONFIG_SYS_I2C_EEPROM_ADDR_OVERFLOW); #endif - if ((ret = i2c_transfer(read, chip << 1, &xaddr[4 - alen], alen, - buffer, len)) != 0) { + ret = _i2c_transfer(adap, read, chip << 1, &xaddr[4 - alen], alen, + buffer, len); + if (ret) { printf("I2C %s: failed %d\n", read ? "read" : "write", ret); - return 1; } return 0; } -int i2c_read(uchar chip, uint addr, int alen, uchar * buffer, int len) +static int ppc4xx_i2c_read(struct i2c_adapter *adap, uchar chip, uint addr, + int alen, uchar *buffer, int len) { - return ppc4xx_i2c_transfer(chip, addr, alen, buffer, len, 1); + return ppc4xx_i2c_transfer(adap, chip, addr, alen, buffer, len, 1); } -int i2c_write(uchar chip, uint addr, int alen, uchar * buffer, int len) +static int ppc4xx_i2c_write(struct i2c_adapter *adap, uchar chip, uint addr, + int alen, uchar *buffer, int len) { - return ppc4xx_i2c_transfer(chip, addr, alen, buffer, len, 0); + return ppc4xx_i2c_transfer(adap, chip, addr, alen, buffer, len, 0); } -#if defined(CONFIG_I2C_MULTI_BUS) -/* - * Functions for multiple I2C bus handling - */ -unsigned int i2c_get_bus_num(void) +static unsigned int ppc4xx_i2c_set_bus_speed(struct i2c_adapter *adap, + unsigned int speed) { - return i2c_bus_num; -} - -int i2c_set_bus_num(unsigned int bus) -{ - if (bus >= CONFIG_SYS_MAX_I2C_BUS) + if (speed != adap->speed) return -1; - - i2c_bus_num = bus; - - return 0; + return speed; } -#endif /* CONFIG_I2C_MULTI_BUS */ -#endif /* CONFIG_HARD_I2C */ + +/* + * Register ppc4xx i2c adapters + */ +#ifdef CONFIG_SYS_I2C_PPC4XX_CH0 +U_BOOT_I2C_ADAP_COMPLETE(ppc4xx_0, ppc4xx_i2c_init, ppc4xx_i2c_probe, + ppc4xx_i2c_read, ppc4xx_i2c_write, + ppc4xx_i2c_set_bus_speed, + CONFIG_SYS_I2C_PPC4XX_SPEED_0, + CONFIG_SYS_I2C_PPC4XX_SLAVE_0, 0) +#endif +#ifdef CONFIG_SYS_I2C_PPC4XX_CH1 +U_BOOT_I2C_ADAP_COMPLETE(ppc4xx_1, ppc4xx_i2c_init, ppc4xx_i2c_probe, + ppc4xx_i2c_read, ppc4xx_i2c_write, + ppc4xx_i2c_set_bus_speed, + CONFIG_SYS_I2C_PPC4XX_SPEED_1, + CONFIG_SYS_I2C_PPC4XX_SLAVE_1, 1) +#endif