From patchwork Mon Aug 24 05:59:38 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vaibhav Hiremath X-Patchwork-Id: 7060871 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id C7FC8C05AC for ; Mon, 24 Aug 2015 06:04:43 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id D9F7A2061D for ; Mon, 24 Aug 2015 06:04:42 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id DC4BB20619 for ; Mon, 24 Aug 2015 06:04:41 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1ZTkqQ-0001FM-HG; Mon, 24 Aug 2015 06:02:58 +0000 Received: from mail-pa0-f54.google.com ([209.85.220.54]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1ZTkq6-00011H-L9 for linux-arm-kernel@lists.infradead.org; Mon, 24 Aug 2015 06:02:39 +0000 Received: by padfa11 with SMTP id fa11so1601032pad.3 for ; Sun, 23 Aug 2015 23:02:17 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=+mDEJcaKxrqS4myUH7Lx2nsqTGKj5DtS/wUaWrI/5nE=; b=h01x1IgyPo28otOO9M6gsSNHAbqxLxbV3zaY+vrnbiNMsJUzg4Cv+lexYVepuxjSFg ZG6/SLeZ5pyJKHA6pS3RV8pbVg0Xn5opj00NMW0kFBC6AcmRZaRWvNDv0ySC4wRHeqEi 7KpBE8hOAQ5saw8C9vrqDXufgJLwHzSdN+aqElW+z5zBVGQhHm3wfZlCJWKVBNJi2e+O UOmBJqRzCDlT5xMUIA0ZXV3U70WtftbVXbVm6DpGUbsYblVUj0eibXqWZDCIt2At97Ic hTaPL3WueFZLClrbjkeWso3R2M65R9vK5Bs6OdNO2b0/Wt7G422cRl5/1+Gyzuc8Js7K XQ/Q== X-Gm-Message-State: ALoCoQm5jcaoqfXcKm0w6y6eSYySSMYU+bO1BpIkUwvlfpF+VO5m8dUu0ntJVTtQMbx8GVfGOmY1 X-Received: by 10.68.234.167 with SMTP id uf7mr42308453pbc.51.1440396137901; Sun, 23 Aug 2015 23:02:17 -0700 (PDT) Received: from localhost.localdomain ([202.62.77.106]) by smtp.gmail.com with ESMTPSA id h16sm15925034pdk.4.2015.08.23.23.02.13 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Sun, 23 Aug 2015 23:02:16 -0700 (PDT) From: Vaibhav Hiremath To: linux-arm-kernel@lists.infradead.org Subject: [PATCH-v5 RESEND 5/5] i2c: pxa: Add ILCR (tLow & tHigh) configuration support Date: Mon, 24 Aug 2015 11:29:38 +0530 Message-Id: <1440395978-9065-6-git-send-email-vaibhav.hiremath@linaro.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1440395978-9065-1-git-send-email-vaibhav.hiremath@linaro.org> References: <1440395978-9065-1-git-send-email-vaibhav.hiremath@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20150823_230238_747294_D851DBF7 X-CRM114-Status: GOOD ( 17.11 ) X-Spam-Score: -2.6 (--) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: devicetree@vger.kernel.org, wsa@the-dreams.de, Yi Zhang , linux-kernel@vger.kernel.org, Vaibhav Hiremath , "Jett.Zhou" , robh+dt@kernel.org, linux-i2c@vger.kernel.org, robert.jarzmik@free.fr MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-5.6 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable 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 With addition of PXA910 family of devices, the TWSI module supports SCL clock adjustment using ILCR register. This patch enables the control and configuration of ICLR through DT properties, i2c-sclk-high-time-ns: SCLK high time (tHigh), for standard/fast/high speed mode i2c-sclk-low-time-ns: SCLK low time (tLow), for standard/fast/high speed mode Note that in case of standard and fast mod, the tLow and tHigh counters are same, and software will use tLow value. Also, brought up devm_clk_get() fn above i2c_pxa_probe_dt(), as it uses clk rate for timing calculations. Signed-off-by: Vaibhav Hiremath Signed-off-by: Jett.Zhou Signed-off-by: Yi Zhang Tested-by: Robert Jarzmik --- drivers/i2c/busses/i2c-pxa.c | 69 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 63 insertions(+), 6 deletions(-) diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index 8d76197..6012ae5 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c @@ -195,6 +195,9 @@ struct pxa_i2c { unsigned long rate; bool highmode_enter; bool disable_after_xfer; + + unsigned int sclk_thigh_load_cnt; + unsigned int sclk_tlow_load_cnt; }; #define _IBMR(i2c) ((i2c)->reg_ibmr) @@ -507,6 +510,36 @@ static void i2c_pxa_set_slave(struct pxa_i2c *i2c, int errcode) #define i2c_pxa_set_slave(i2c, err) do { } while (0) #endif +static void i2c_pxa_do_sclk_adj(struct pxa_i2c *i2c) +{ + unsigned int reg_ilcr; + + if (!i2c->reg_ilcr) + return; + + reg_ilcr = readl(_ILCR(i2c)); + + /* For standard/fast mode tlow and thigh counters are same */ + if (i2c->sclk_tlow_load_cnt) { + unsigned int mask, shift; + + mask = i2c->high_mode ? ILCR_HLVL_MASK : + i2c->fast_mode ? ILCR_FLV_MASK : ILCR_SLV_MASK; + shift = i2c->high_mode ? ILCR_HLVL_SHIFT : + i2c->fast_mode ? ILCR_FLV_SHIFT : ILCR_SLV_SHIFT; + + reg_ilcr &= ~mask; + reg_ilcr |= i2c->sclk_tlow_load_cnt << shift; + } + + if (i2c->high_mode && i2c->sclk_thigh_load_cnt) { + reg_ilcr &= ~ILCR_HLVH_MASK; + reg_ilcr |= i2c->sclk_thigh_load_cnt << ILCR_HLVH_SHIFT; + } + + writel(reg_ilcr, _ILCR(i2c)); +} + static void i2c_pxa_reset(struct pxa_i2c *i2c) { pr_debug("Resetting I2C Controller Unit\n"); @@ -526,6 +559,8 @@ static void i2c_pxa_reset(struct pxa_i2c *i2c) writel(I2C_ICR_INIT | (i2c->fast_mode ? ICR_FM : 0), _ICR(i2c)); writel(readl(_ICR(i2c)) | (i2c->high_mode ? ICR_HS : 0), _ICR(i2c)); + i2c_pxa_do_sclk_adj(i2c); + #ifdef CONFIG_I2C_PXA_SLAVE dev_info(&i2c->adap.dev, "Enabling slave mode\n"); writel(readl(_ICR(i2c)) | ICR_SADIE | ICR_ALDIE | ICR_SSDIE, _ICR(i2c)); @@ -1198,6 +1233,26 @@ static int i2c_pxa_probe_dt(struct platform_device *pdev, struct pxa_i2c *i2c, *i2c_types = (enum pxa_i2c_types)(of_id->data); + /* optional properties */ + if (of_device_is_compatible(np, "mrvl,mmp-twsi")) { + unsigned int tlow = 0, thigh = 0; + unsigned int clk_ns; + + /* clock time in nsec */ + clk_ns = 1000000 / (i2c->rate / 1000); + + of_property_read_u32(np, "i2c-sclk-high-time-ns", &thigh); + i2c->sclk_thigh_load_cnt = thigh / clk_ns; + + of_property_read_u32(np, "i2c-sclk-low-time-ns", &tlow); + i2c->sclk_tlow_load_cnt = tlow / clk_ns; + + /* For std/fast mode tlow & thigh have same bit-fields */ + if (!i2c->high_mode && + (i2c->sclk_tlow_load_cnt != i2c->sclk_thigh_load_cnt)) + dev_warn(&i2c->adap.dev, + "mismatch of tLow & tHigh values, using tLow\n"); + } return 0; } @@ -1248,6 +1303,14 @@ static int i2c_pxa_probe(struct platform_device *dev) return irq; } + i2c->clk = devm_clk_get(&dev->dev, NULL); + if (IS_ERR(i2c->clk)) { + dev_err(&dev->dev, "failed to get the clk: %ld\n", PTR_ERR(i2c->clk)); + return PTR_ERR(i2c->clk); + } + + i2c->rate = clk_get_rate(i2c->clk); + /* Default adapter num to device id; i2c_pxa_probe_dt can override. */ i2c->adap.nr = dev->id; @@ -1265,12 +1328,6 @@ static int i2c_pxa_probe(struct platform_device *dev) strlcpy(i2c->adap.name, "pxa_i2c-i2c", sizeof(i2c->adap.name)); - i2c->clk = devm_clk_get(&dev->dev, NULL); - if (IS_ERR(i2c->clk)) { - dev_err(&dev->dev, "failed to get the clk: %ld\n", PTR_ERR(i2c->clk)); - return PTR_ERR(i2c->clk); - } - i2c->reg_ibmr = i2c->reg_base + pxa_reg_layout[i2c_type].ibmr; i2c->reg_idbr = i2c->reg_base + pxa_reg_layout[i2c_type].idbr; i2c->reg_icr = i2c->reg_base + pxa_reg_layout[i2c_type].icr;