From patchwork Fri Jun 22 04:12:02 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Troy Kisky X-Patchwork-Id: 166478 X-Patchwork-Delegate: hs@denx.de 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 E160BB6FA1 for ; Fri, 22 Jun 2012 14:13:38 +1000 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 73BAC280CB; Fri, 22 Jun 2012 06:13:20 +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 TObsJP3cJv+d; Fri, 22 Jun 2012 06:13:20 +0200 (CEST) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 98D5A280AC; Fri, 22 Jun 2012 06:12:40 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 9407A28088 for ; Fri, 22 Jun 2012 06:12:32 +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 zq30xuu+IaVj for ; Fri, 22 Jun 2012 06:12:31 +0200 (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 mail-pb0-f44.google.com (mail-pb0-f44.google.com [209.85.160.44]) by theia.denx.de (Postfix) with ESMTPS id 6F2D92808D for ; Fri, 22 Jun 2012 06:12:29 +0200 (CEST) Received: by pbcwy7 with SMTP id wy7so2919149pbc.3 for ; Thu, 21 Jun 2012 21:12:27 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references :x-gm-message-state; bh=RBK2DNIbnBEEaXhLzr27wkZbBjKNmD1930erj2VWdnM=; b=nNFFuOCZPg9NLouzml5F9oBBKydAKil0HWI3rA4zrFhcABPx38pD+5EmQG8ABU1+M5 umI5s2hlOfb+m0H7XkKy4261N/V3tiR/7qcixNlyKTd/y1rLrv4wywgvk7KmICaDQqBO KkG8X2wjqgVsy3hLQ3hrXu8sHt8JBhAz52cs5D8w+v4zaOAUWoh7MiiiLyQb966mIqRN a4voPf2S+CocAt/VtsNWZcnDXrmAWFHIdUlxiYw6jrgFMxV+pqzYZM2MZYTwSyGvoX2e Zpyw9oecsoOSzefR8uWu2XJDIql9jCDOUvwEGnO2SRZRCrZb5nVUNoxNpvGvkbTajmWf aemA== Received: by 10.68.132.201 with SMTP id ow9mr4907727pbb.160.1340338347539; Thu, 21 Jun 2012 21:12:27 -0700 (PDT) Received: from officeserver-2 ([70.96.116.236]) by mx.google.com with ESMTPS id hc7sm37666635pbc.54.2012.06.21.21.12.22 (version=TLSv1/SSLv3 cipher=OTHER); Thu, 21 Jun 2012 21:12:24 -0700 (PDT) Received: from tkisky by officeserver-2 with local (Exim 4.76) (envelope-from ) id 1ShvEL-00032d-IG; Thu, 21 Jun 2012 21:12:21 -0700 From: Troy Kisky To: hs@denx.de, sbabic@denx.de Date: Thu, 21 Jun 2012 21:12:02 -0700 Message-Id: <1340338339-11626-7-git-send-email-troy.kisky@boundarydevices.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1340338339-11626-1-git-send-email-troy.kisky@boundarydevices.com> References: <1340338339-11626-1-git-send-email-troy.kisky@boundarydevices.com> X-Gm-Message-State: ALoCoQkcvTl1a0KE60owAMEB8oGGmNWIt4vrNQ+Fj6WC1bBVoqkI48ulJ0SCez38Ehfaac+UnBVt Cc: u-boot@lists.denx.de, r49496@freescale.com, jason.hui@linaro.org Subject: [U-Boot] [PATCH 07/24] mxc_i2c: combine i2c_imx_bus_busy and i2c_imx_trx_complete into wait_for_sr_state 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 Not using udelay gives a more accurate timeout. The current implementation of udelay in imx-common does not seem to wait at all for a udelay(1). Signed-off-by: Troy Kisky --- drivers/i2c/mxc_i2c.c | 71 ++++++++++++++++--------------------------------- 1 file changed, 23 insertions(+), 48 deletions(-) diff --git a/drivers/i2c/mxc_i2c.c b/drivers/i2c/mxc_i2c.c index 4f12b9e..7b1b75c 100644 --- a/drivers/i2c/mxc_i2c.c +++ b/drivers/i2c/mxc_i2c.c @@ -63,8 +63,6 @@ struct mxc_i2c_regs { #error "define CONFIG_SYS_I2C_BASE to use the mxc_i2c driver" #endif -#define I2C_MAX_TIMEOUT 10000 - static u16 i2c_clk_div[50][2] = { { 22, 0x20 }, { 24, 0x21 }, { 26, 0x22 }, { 28, 0x23 }, { 30, 0x00 }, { 32, 0x24 }, { 36, 0x25 }, { 40, 0x26 }, @@ -164,48 +162,25 @@ unsigned int i2c_get_bus_speed(void) return mxc_get_clock(MXC_IPG_PERCLK) / i2c_clk_div[clk_div][0]; } -/* - * Wait for bus to be busy (or free if for_busy = 0) - * - * for_busy = 1: Wait for IBB to be asserted - * for_busy = 0: Wait for IBB to be de-asserted - */ -int i2c_imx_bus_busy(int for_busy) -{ - struct mxc_i2c_regs *i2c_regs = (struct mxc_i2c_regs *)I2C_BASE; - unsigned int temp; - - int timeout = I2C_MAX_TIMEOUT; - - while (timeout--) { - temp = readb(&i2c_regs->i2sr); +#define ST_BUS_IDLE (0 | (I2SR_IBB << 8)) +#define ST_BUS_BUSY (I2SR_IBB | (I2SR_IBB << 8)) +#define ST_IIF (I2SR_IIF | (I2SR_IIF << 8)) - if (for_busy && (temp & I2SR_IBB)) - return 0; - if (!for_busy && !(temp & I2SR_IBB)) - return 0; - - udelay(1); - } - - return 1; -} - -/* - * Wait for transaction to complete - */ -int i2c_imx_trx_complete(void) +static unsigned wait_for_sr_state(struct mxc_i2c_regs *i2c_regs, unsigned state) { - struct mxc_i2c_regs *i2c_regs = (struct mxc_i2c_regs *)I2C_BASE; - int timeout = I2C_MAX_TIMEOUT; - - while (timeout--) { - if (readb(&i2c_regs->i2sr) & I2SR_IIF) - return 0; - - udelay(1); + unsigned sr; + ulong elapsed; + ulong start_time = get_timer(0); + for (;;) { + sr = readb(&i2c_regs->i2sr); + if ((sr & (state >> 8)) == (unsigned char)state) + return sr; + elapsed = get_timer(start_time); + if (elapsed > (CONFIG_SYS_HZ / 10)) /* .1 seconds */ + break; } - + printf("%s: failed sr=%x cr=%x state=%x\n", __func__, + sr, readb(&i2c_regs->i2cr), state); return -ETIMEDOUT; } @@ -215,7 +190,7 @@ static int tx_byte(struct mxc_i2c_regs *i2c_regs, u8 byte) writeb(0, &i2c_regs->i2sr); writeb(byte, &i2c_regs->i2dr); - ret = i2c_imx_trx_complete(); + ret = wait_for_sr_state(i2c_regs, ST_IIF); if (ret < 0) return ret; ret = readb(&i2c_regs->i2sr); @@ -245,8 +220,8 @@ int i2c_imx_start(void) temp |= I2CR_MSTA; writeb(temp, &i2c_regs->i2cr); - result = i2c_imx_bus_busy(1); - if (result) + result = wait_for_sr_state(i2c_regs, ST_BUS_BUSY); + if (result < 0) return result; temp |= I2CR_MTX | I2CR_TX_NO_AK; @@ -268,7 +243,7 @@ void i2c_imx_stop(void) temp &= ~(I2CR_MSTA | I2CR_MTX); writeb(temp, &i2c_regs->i2cr); - i2c_imx_bus_busy(0); + wait_for_sr_state(i2c_regs, ST_BUS_IDLE); /* Disable I2C controller */ writeb(0, &i2c_regs->i2cr); @@ -333,8 +308,8 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buf, int len) /* read data */ for (i = 0; i < len; i++) { - ret = i2c_imx_trx_complete(); - if (ret) + ret = wait_for_sr_state(i2c_regs, ST_IIF); + if (ret < 0) return ret; /* @@ -345,7 +320,7 @@ int i2c_read(uchar chip, uint addr, int alen, uchar *buf, int len) temp = readb(&i2c_regs->i2cr); temp &= ~(I2CR_MSTA | I2CR_MTX); writeb(temp, &i2c_regs->i2cr); - i2c_imx_bus_busy(0); + wait_for_sr_state(i2c_regs, ST_BUS_IDLE); } else if (i == (len - 2)) { temp = readb(&i2c_regs->i2cr); temp |= I2CR_TX_NO_AK;