From patchwork Tue Oct 1 10:33:40 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yuvaraj CD X-Patchwork-Id: 2969331 Return-Path: X-Original-To: patchwork-linux-samsung-soc@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 1E343BFF0B for ; Tue, 1 Oct 2013 10:34:13 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id CEDE02034D for ; Tue, 1 Oct 2013 10:34:11 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 6EC072024A for ; Tue, 1 Oct 2013 10:34:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752364Ab3JAKeJ (ORCPT ); Tue, 1 Oct 2013 06:34:09 -0400 Received: from mail-pd0-f182.google.com ([209.85.192.182]:63085 "EHLO mail-pd0-f182.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753098Ab3JAKeI (ORCPT ); Tue, 1 Oct 2013 06:34:08 -0400 Received: by mail-pd0-f182.google.com with SMTP id r10so7006093pdi.13 for ; Tue, 01 Oct 2013 03:34:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id; bh=Fe/vWI/Yex5AYTzJcv3Aw6qISfM6Zcn1JjR59ePTQoE=; b=CViAth0XnTaYbX7LedK8mXi97+eoWKs4i79iH/BnQgGoCz9Y5CIuCfMThrQdh3vdJk Apd2tZB2WRavLeb7LyJTNrHPmC6zcOAH3H7blsORBmp3BQu7tI3GZJYM/I7dAfbT+MpX XdrNd23XJHyvrfZ/FMyuakvFnuBipgFQ2o6OF8U3+hEP/6hhQndIYgGUnZB/VJ3OiwAT s5fhZ0UsEFGUU0VK00VC4ltUT8+i/4OPx6ANylJI/ib7M9i6YvXMmCF96rEacXB/bmhY do2mIAThbeM6T1KnskbShZlGiZ4oGPcXDBb2noe36Uhwp8YCnV0k2QeaucNKG+Bhykju Scfw== X-Received: by 10.68.190.229 with SMTP id gt5mr2281664pbc.177.1380623647045; Tue, 01 Oct 2013 03:34:07 -0700 (PDT) Received: from yuvaraj-ubuntu.sisodomain.com ([115.113.119.130]) by mx.google.com with ESMTPSA id lm2sm7404107pab.2.1969.12.31.16.00.00 (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Tue, 01 Oct 2013 03:34:06 -0700 (PDT) From: Yuvaraj Kumar C D To: wsa@the-dreams.de, pawel.moll@arm.com, mark.rutland@arm.com, ijc+devicetree@hellion.org.uk, ben-linux@fluff.org, kgene.kim@samsung.com, swarren@wwwdotorg.org, rob.herring@calxeda.com, linux-i2c@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-samsung-soc@vger.kernel.org, devicetree@vger.kernel.org Cc: ks.giri@samsung.com, aditya.ps@samsung.com, Vasanth Ananthan , Vasanth Ananthan , Yuvaraj Kumar C D Subject: [PATCH] i2c: s3c2410 : Add polling mode support Date: Tue, 1 Oct 2013 16:03:40 +0530 Message-Id: <1380623620-31901-1-git-send-email-yuvaraj.cd@samsung.com> X-Mailer: git-send-email 1.7.9.5 Sender: linux-samsung-soc-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-samsung-soc@vger.kernel.org X-Spam-Status: No, score=-4.0 required=5.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, KHOP_BIG_TO_CC, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, T_DKIM_INVALID,UNPARSEABLE_RELAY autolearn=ham version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Vasanth Ananthan This patch adds polling mode support for i2c-s3c2410 driver.The SATA PHY controller's CMU and TRSV block's are of I2C register map in exynos5250.These blocks can be configured using i2c. But i2c controller instance on which these block's sits lacks an interrupt line.Also the current i2c-s3c2410 driver is only interrupt driven, thus a polling mode support is required in the driver for supporting this controller. This patch adds this support to the driver. Signed-off-by: Vasanth Ananthan Signed-off-by: Yuvaraj Kumar C D --- .../devicetree/bindings/i2c/i2c-s3c2410.txt | 2 + drivers/i2c/busses/i2c-s3c2410.c | 68 ++++++++++++++++---- 2 files changed, 59 insertions(+), 11 deletions(-) diff --git a/Documentation/devicetree/bindings/i2c/i2c-s3c2410.txt b/Documentation/devicetree/bindings/i2c/i2c-s3c2410.txt index 296eb45..bc928a0 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-s3c2410.txt +++ b/Documentation/devicetree/bindings/i2c/i2c-s3c2410.txt @@ -10,6 +10,8 @@ Required properties: inside HDMIPHY block found on several samsung SoCs (d) "samsung, exynos5440-i2c", for s3c2440-like i2c used on EXYNOS5440 which does not need GPIO configuration. + (e) "samsung,exynos5-sata-phy-i2c", for s3c2440-like i2c used as + a host to SATA PHY controller on an internal bus. - reg: physical base address of the controller and length of memory mapped region. - interrupts: interrupt number to the cpu. diff --git a/drivers/i2c/busses/i2c-s3c2410.c b/drivers/i2c/busses/i2c-s3c2410.c index 3535f3c..2b279d0 100644 --- a/drivers/i2c/busses/i2c-s3c2410.c +++ b/drivers/i2c/busses/i2c-s3c2410.c @@ -85,6 +85,7 @@ #define QUIRK_S3C2440 (1 << 0) #define QUIRK_HDMIPHY (1 << 1) #define QUIRK_NO_GPIO (1 << 2) +#define QUIRK_POLL (1 << 3) /* Max time to wait for bus to become idle after a xfer (in us) */ #define S3C2410_IDLE_TIMEOUT 5000 @@ -141,6 +142,8 @@ static struct platform_device_id s3c24xx_driver_ids[] = { }; MODULE_DEVICE_TABLE(platform, s3c24xx_driver_ids); +static int i2c_s3c_irq_nextbyte(struct s3c24xx_i2c *i2c, unsigned long iicstat); + #ifdef CONFIG_OF static const struct of_device_id s3c24xx_i2c_match[] = { { .compatible = "samsung,s3c2410-i2c", .data = (void *)0 }, @@ -149,6 +152,8 @@ static const struct of_device_id s3c24xx_i2c_match[] = { .data = (void *)(QUIRK_S3C2440 | QUIRK_HDMIPHY | QUIRK_NO_GPIO) }, { .compatible = "samsung,exynos5440-i2c", .data = (void *)(QUIRK_S3C2440 | QUIRK_NO_GPIO) }, + { .compatible = "samsung,exynos5-sata-phy-i2c", + .data = (void *)(QUIRK_S3C2440 | QUIRK_POLL | QUIRK_NO_GPIO) }, {}, }; MODULE_DEVICE_TABLE(of, s3c24xx_i2c_match); @@ -187,7 +192,8 @@ static inline void s3c24xx_i2c_master_complete(struct s3c24xx_i2c *i2c, int ret) if (ret) i2c->msg_idx = ret; - wake_up(&i2c->wait); + if (!(i2c->quirks & QUIRK_POLL)) + wake_up(&i2c->wait); } static inline void s3c24xx_i2c_disable_ack(struct s3c24xx_i2c *i2c) @@ -224,6 +230,22 @@ static inline void s3c24xx_i2c_enable_irq(struct s3c24xx_i2c *i2c) writel(tmp | S3C2410_IICCON_IRQEN, i2c->regs + S3C2410_IICCON); } +static bool is_ack(struct s3c24xx_i2c *i2c) +{ + u32 time_out = i2c->tx_setup; + + while (--time_out) { + if (readl(i2c->regs + S3C2410_IICCON) + & S3C2410_IICCON_IRQPEND) { + if (!(readl(i2c->regs + S3C2410_IICSTAT) + & S3C2410_IICSTAT_LASTBIT)) + return true; + } + udelay(time_out); + } + + return false; +} /* s3c24xx_i2c_message_start * @@ -268,6 +290,16 @@ static void s3c24xx_i2c_message_start(struct s3c24xx_i2c *i2c, stat |= S3C2410_IICSTAT_START; writel(stat, i2c->regs + S3C2410_IICSTAT); + + if (i2c->quirks & QUIRK_POLL) { + while ((i2c->msg_num != 0) && is_ack(i2c)) { + i2c_s3c_irq_nextbyte(i2c, stat); + stat = readl(i2c->regs + S3C2410_IICSTAT); + + if (stat & S3C2410_IICSTAT_ARBITR) + dev_err(i2c->dev, "deal with arbitration loss\n"); + } + } } static inline void s3c24xx_i2c_stop(struct s3c24xx_i2c *i2c, int ret) @@ -675,6 +707,15 @@ static int s3c24xx_i2c_doxfer(struct s3c24xx_i2c *i2c, s3c24xx_i2c_enable_irq(i2c); s3c24xx_i2c_message_start(i2c, msgs); + if (i2c->quirks & QUIRK_POLL) { + ret = i2c->msg_idx; + + if (ret != num) + dev_dbg(i2c->dev, "incomplete xfer (%d)\n", ret); + + goto out; + } + timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5); ret = i2c->msg_idx; @@ -820,6 +861,9 @@ static int s3c24xx_i2c_clockrate(struct s3c24xx_i2c *i2c, unsigned int *got) if (div1 == 512) iiccon |= S3C2410_IICCON_TXDIV_512; + if (i2c->quirks & QUIRK_POLL) + iiccon |= S3C2410_IICCON_SCALE(2); + writel(iiccon, i2c->regs + S3C2410_IICCON); if (i2c->quirks & QUIRK_S3C2440) { @@ -1117,18 +1161,20 @@ static int s3c24xx_i2c_probe(struct platform_device *pdev) * ensure no current IRQs pending */ - i2c->irq = ret = platform_get_irq(pdev, 0); - if (ret <= 0) { - dev_err(&pdev->dev, "cannot find IRQ\n"); - return ret; - } + if (!(i2c->quirks & QUIRK_POLL)) { + i2c->irq = ret = platform_get_irq(pdev, 0); + if (ret <= 0) { + dev_err(&pdev->dev, "cannot find IRQ\n"); + return ret; + } - ret = devm_request_irq(&pdev->dev, i2c->irq, s3c24xx_i2c_irq, 0, - dev_name(&pdev->dev), i2c); + ret = devm_request_irq(&pdev->dev, i2c->irq, s3c24xx_i2c_irq, 0, + dev_name(&pdev->dev), i2c); - if (ret != 0) { - dev_err(&pdev->dev, "cannot claim IRQ %d\n", i2c->irq); - return ret; + if (ret != 0) { + dev_err(&pdev->dev, "cannot claim IRQ %d\n", i2c->irq); + return ret; + } } ret = s3c24xx_i2c_register_cpufreq(i2c);