From patchwork Mon Nov 23 15:22:36 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Philby John X-Patchwork-Id: 62200 Received: from arroyo.ext.ti.com (arroyo.ext.ti.com [192.94.94.40]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id nANFOvCO003081 for ; Mon, 23 Nov 2009 15:24:58 GMT Received: from dlep35.itg.ti.com ([157.170.170.118]) by arroyo.ext.ti.com (8.13.7/8.13.7) with ESMTP id nANFMrBV024792 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Mon, 23 Nov 2009 09:22:53 -0600 Received: from linux.omap.com (localhost [127.0.0.1]) by dlep35.itg.ti.com (8.13.7/8.13.7) with ESMTP id nANFMqjN007992; Mon, 23 Nov 2009 09:22:53 -0600 (CST) Received: from linux.omap.com (localhost [127.0.0.1]) by linux.omap.com (Postfix) with ESMTP id 698C980627; Mon, 23 Nov 2009 09:22:52 -0600 (CST) X-Original-To: davinci-linux-open-source@linux.davincidsp.com Delivered-To: davinci-linux-open-source@linux.davincidsp.com Received: from dflp53.itg.ti.com (dflp53.itg.ti.com [128.247.5.6]) by linux.omap.com (Postfix) with ESMTP id 4BC2380626 for ; Mon, 23 Nov 2009 09:22:50 -0600 (CST) Received: from neches.ext.ti.com (localhost [127.0.0.1]) by dflp53.itg.ti.com (8.13.8/8.13.8) with ESMTP id nANFMorA018130 for ; Mon, 23 Nov 2009 09:22:50 -0600 (CST) Received: from mail153-tx2-R.bigfish.com (mail-tx2.bigfish.com [65.55.88.114]) by neches.ext.ti.com (8.13.7/8.13.7) with ESMTP id nANFMnfP021910 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=FAIL) for ; Mon, 23 Nov 2009 09:22:50 -0600 Received: from mail153-tx2 (localhost.localdomain [127.0.0.1]) by mail153-tx2-R.bigfish.com (Postfix) with ESMTP id AB4BF14D82DB for ; Mon, 23 Nov 2009 15:22:49 +0000 (UTC) X-SpamScore: 4 X-BigFish: vps4(z34a4jzzz1202hzzz2dh6bh43j61h) X-Spam-TCS-SCL: 0:0 X-MS-Exchange-Organization-Antispam-Report: OrigIP: 206.112.117.35; Service: EHS Received: from mail153-tx2 (localhost.localdomain [127.0.0.1]) by mail153-tx2 (MessageSwitch) id 1258989749216347_27178; Mon, 23 Nov 2009 15:22:29 +0000 (UTC) Received: from TX2EHSMHS005.bigfish.com (unknown [10.9.14.244]) by mail153-tx2.bigfish.com (Postfix) with ESMTP id 39BF3D8006B for ; Mon, 23 Nov 2009 15:22:20 +0000 (UTC) Received: from imap.sh.mvista.com (206.112.117.35) by TX2EHSMHS005.bigfish.com (10.9.99.105) with Microsoft SMTP Server id 14.0.482.32; Mon, 23 Nov 2009 15:22:17 +0000 Received: from [10.161.2.200] (unknown [10.161.2.200]) by imap.sh.mvista.com (Postfix) with SMTP id 538333ECC; Mon, 23 Nov 2009 07:22:15 -0800 (PST) Subject: [PATCH v1] i2c: Davinci i2c bus recovery procedure to come out of time out conditions From: Philby John To: linux-i2c@vger.kernel.org Organization: MontaVista Date: Mon, 23 Nov 2009 20:52:36 +0530 Message-ID: <1258989756.20007.227.camel@localhost.localdomain> MIME-Version: 1.0 X-Mailer: Evolution 2.24.5 (2.24.5-2.fc10) X-Reverse-DNS: unknown Cc: "davinci-linux-open-source@linux.davincidsp.com" X-BeenThere: davinci-linux-open-source@linux.davincidsp.com X-Mailman-Version: 2.1.12 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: davinci-linux-open-source-bounces@linux.davincidsp.com Errors-To: davinci-linux-open-source-bounces@linux.davincidsp.com diff --git a/drivers/i2c/busses/i2c-davinci.c b/drivers/i2c/busses/i2c-davinci.c index 67d88cc..6b4a550 100644 --- a/drivers/i2c/busses/i2c-davinci.c +++ b/drivers/i2c/busses/i2c-davinci.c @@ -35,6 +35,7 @@ #include #include #include +#include #include @@ -43,6 +44,7 @@ /* ----- global defines ----------------------------------------------- */ #define DAVINCI_I2C_TIMEOUT (1*HZ) +#define DAVINCI_I2C_MAX_TRIES 2 #define I2C_DAVINCI_INTR_ALL (DAVINCI_I2C_IMR_AAS | \ DAVINCI_I2C_IMR_SCD | \ DAVINCI_I2C_IMR_ARDY | \ @@ -134,6 +136,38 @@ static inline u16 davinci_i2c_read_reg(struct davinci_i2c_dev *i2c_dev, int reg) return __raw_readw(i2c_dev->base + reg); } +/* Generate a pulse on the i2c clock pin. */ +static void pulse_i2c_clock(void) +{ + gpio_set_value(14, 0); + udelay(20); + gpio_set_value(14, 1); + udelay(20); +} + +/* This routine does i2c bus recovery as specified in the + * i2c protocol Rev. 03 section 3.16 titled "Bus clear" + */ +static void i2c_recover_bus(struct davinci_i2c_dev *dev) +{ + u16 i; + u32 flag = 0; + + dev_err(dev->dev, "initiating i2c bus recovery\n"); + /* Send NACK to the slave */ + flag = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG); + flag |= DAVINCI_I2C_MDR_NACK; + /* write the data into mode register */ + davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag); + /* Send high and low on the SCL line */ + for (i = 0; i < 9; i++) + pulse_i2c_clock(); + /* Send STOP */ + flag = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG); + MOD_REG_BIT(flag, DAVINCI_I2C_MDR_STP, 1); + davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag); +} + /* * This functions configures I2C and brings I2C out of reset. * This function is called during I2C init function. This function @@ -221,19 +255,26 @@ static int i2c_davinci_wait_bus_not_busy(struct davinci_i2c_dev *dev, char allow_sleep) { unsigned long timeout; + static u16 to_cnt = 0; timeout = jiffies + dev->adapter.timeout; while (davinci_i2c_read_reg(dev, DAVINCI_I2C_STR_REG) - & DAVINCI_I2C_STR_BB) { - if (time_after(jiffies, timeout)) { - dev_warn(dev->dev, - "timeout waiting for bus ready\n"); - return -ETIMEDOUT; + & DAVINCI_I2C_STR_BB) { + if (to_cnt <= DAVINCI_I2C_MAX_TRIES) { + if (time_after(jiffies, timeout)) { + dev_warn(dev->dev, + "timeout waiting for bus ready\n"); + to_cnt++; + return -ETIMEDOUT; + } else { + to_cnt = 0; + i2c_recover_bus(dev); + i2c_davinci_init(dev); + } } if (allow_sleep) schedule_timeout(1); } - return 0; } @@ -310,6 +351,7 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop) dev->adapter.timeout); if (r == 0) { dev_err(dev->dev, "controller timed out\n"); + i2c_recover_bus(dev); i2c_davinci_init(dev); dev->buf_len = 0; return -ETIMEDOUT;