From patchwork Wed Feb 26 21:37:01 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Benoit Cousson X-Patchwork-Id: 3728721 Return-Path: X-Original-To: patchwork-linux-sh@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 24CEB9F2F7 for ; Wed, 26 Feb 2014 21:37:25 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 0E533201FB for ; Wed, 26 Feb 2014 21:37:24 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 5F9CB20121 for ; Wed, 26 Feb 2014 21:37:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751466AbaBZVhV (ORCPT ); Wed, 26 Feb 2014 16:37:21 -0500 Received: from mail-wi0-f174.google.com ([209.85.212.174]:48885 "EHLO mail-wi0-f174.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751437AbaBZVhV (ORCPT ); Wed, 26 Feb 2014 16:37:21 -0500 Received: by mail-wi0-f174.google.com with SMTP id f8so6474895wiw.1 for ; Wed, 26 Feb 2014 13:37:19 -0800 (PST) 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; bh=gubGSP5K8SrcRHbEGEsl5cfMr9YZYCv1oiC0aXXNvnU=; b=U2zRox3TWzaOQUMtCOxjrDCmSUwKmZqe25c0geqHfUvRJedZ4nfn4/bGGrInigMGa0 ZGXvxi6n+4ewV2T1MiFoKMyfxHYJtJxS6ALabNpCFJx2lAQKJbJyFH8gxWFId2abTdvg rJQBIO6t4iSYiZLO14/SqXQHqUStPI07uskhUu3g0m4ATNvzifu5s2X0qQwHOpS6hAbY hHKQRr00f8plJx+8AoZEAnac43pHmWBcmj/w+kfCX2VzVOJpxBjCC9hLkRCkYGU9fpJP kJWYYuQfC4RN1VDE+eKPuce0v3JRKPtnBhCW/1PaArDyZG4cWn1zYuZc3QviK2Lqy30S mYvw== X-Gm-Message-State: ALoCoQmTX08Yxk3w7+fCDxhblqN2ekwLlrMIP0XcmMIR3/RIkwYftdQxjXU9cvPEy3tjGaUbL4Rn X-Received: by 10.194.170.167 with SMTP id an7mr4399530wjc.39.1393450639643; Wed, 26 Feb 2014 13:37:19 -0800 (PST) Received: from localhost.localdomain (lau06-1-82-228-246-9.fbx.proxad.net. [82.228.246.9]) by mx.google.com with ESMTPSA id jw4sm5669581wjc.20.2014.02.26.13.37.17 for (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Wed, 26 Feb 2014 13:37:18 -0800 (PST) From: Benoit Cousson To: laurent.pinchart@ideasonboard.com Cc: linux-sh@vger.kernel.org, magnus.damm@gmail.com, ptitiano@baylibre.com, Benoit Cousson , Benoit Cousson , Mike Turquette , Laurent Pinchart Subject: [PATCH v2] clk: shmobile: rcar-gen2: Use kick bit to allow Z clock frequency change Date: Wed, 26 Feb 2014 22:37:01 +0100 Message-Id: <1393450621-5089-1-git-send-email-bcousson@baylibre.com> X-Mailer: git-send-email 1.8.3.2 Sender: linux-sh-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-sh@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, 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 The Z clock frequency change is effective only after setting the kick bit located in the FRQCRB register. Without that, the CA15 CPUs clock rate will never change. Fix that by checking if the kick bit is cleared and enable it to make the clock rate change effective. The bit is cleared automatically upon completion. Note: The kick bit is used as well to change 3 other emulation clocks: Debug Trace port clock (ZTR), Debug Trace bus clock (ZT), and Debug clock (ZTRD2). It is not clear from the spec [1] if there is any relation between the CPU clock rate and these emulation clocks. Moreover, these clocks are probably supposed to be controled by an external debugger / tracer like Lauterbach PowerTrace. For all these reasons, the current implementation does not expose these clock nodes and thus does not have to consider the multiple accesses to the kick bit. Signed-off-by: Benoit Cousson Cc: Mike Turquette Cc: Laurent Pinchart [1] R-Car-H2-v0.6-en.pdf - page 186 Acked-by: Laurent Pinchart --- v2: Add more comments about worst case latency and fix some minors nits. --- drivers/clk/shmobile/clk-rcar-gen2.c | 41 ++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/drivers/clk/shmobile/clk-rcar-gen2.c b/drivers/clk/shmobile/clk-rcar-gen2.c index a59ec21..0246251 100644 --- a/drivers/clk/shmobile/clk-rcar-gen2.c +++ b/drivers/clk/shmobile/clk-rcar-gen2.c @@ -26,6 +26,8 @@ struct rcar_gen2_cpg { void __iomem *reg; }; +#define CPG_FRQCRB 0x00000004 +#define CPG_FRQCRB_KICK BIT(31) #define CPG_SDCKCR 0x00000074 #define CPG_PLL0CR 0x000000d8 #define CPG_FRQCRC 0x000000e0 @@ -45,6 +47,7 @@ struct rcar_gen2_cpg { struct cpg_z_clk { struct clk_hw hw; void __iomem *reg; + void __iomem *kick_reg; }; #define to_z_clk(_hw) container_of(_hw, struct cpg_z_clk, hw) @@ -83,17 +86,50 @@ static int cpg_z_clk_set_rate(struct clk_hw *hw, unsigned long rate, { struct cpg_z_clk *zclk = to_z_clk(hw); unsigned int mult; - u32 val; + u32 val, kick; + unsigned int i; mult = div_u64((u64)rate * 32, parent_rate); mult = clamp(mult, 1U, 32U); + if (clk_readl(zclk->kick_reg) & CPG_FRQCRB_KICK) + return -EBUSY; + val = clk_readl(zclk->reg); val &= ~CPG_FRQCRC_ZFC_MASK; val |= (32 - mult) << CPG_FRQCRC_ZFC_SHIFT; clk_writel(val, zclk->reg); - return 0; + /* + * Set KICK bit in FRQCRB to update hardware setting and wait for + * clock change completion. + * + * Note: The KICK bit is used as well to change the emulation clocks: + * Debug Trace port (ZTR), Debug Trace bus (ZT) and Debug (ZTRD2). + * Since the current implementation does not expose these clock nodes, + * it does not protect the register access using a lock. + */ + kick = clk_readl(zclk->kick_reg); + kick |= CPG_FRQCRB_KICK; + clk_writel(kick, zclk->kick_reg); + + /* + * Note: There is no HW information about the worst case latency. + * + * Using experimental measurements, it seems that no more than + * ~10 iterations are needed, independently of the CPU rate. + * Since this value might be dependant of external xtal rate, pll1 + * rate or even the other emulation clocks rate, use 1000 as a + * "super" safe value. + */ + for (i = 1000; i; i--) { + if (clk_readl(zclk->kick_reg) & CPG_FRQCRB_KICK) + cpu_relax(); + else + return 0; + } + + return -ETIMEDOUT; } static const struct clk_ops cpg_z_clk_ops = { @@ -120,6 +156,7 @@ static struct clk * __init cpg_z_clk_register(struct rcar_gen2_cpg *cpg) init.num_parents = 1; zclk->reg = cpg->reg + CPG_FRQCRC; + zclk->kick_reg = cpg->reg + CPG_FRQCRB; zclk->hw.init = &init; clk = clk_register(NULL, &zclk->hw);