From patchwork Mon Aug 24 09:40:48 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gabriel Fernandez X-Patchwork-Id: 7063021 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 5C614C05AC for ; Mon, 24 Aug 2015 09:44:41 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 25A3F2061E for ; Mon, 24 Aug 2015 09:44:40 +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 0420220619 for ; Mon, 24 Aug 2015 09:44:39 +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 1ZToH3-0007L2-FY; Mon, 24 Aug 2015 09:42:41 +0000 Received: from mail-wi0-f180.google.com ([209.85.212.180]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1ZToGu-000769-8V for linux-arm-kernel@lists.infradead.org; Mon, 24 Aug 2015 09:42:33 +0000 Received: by wicne3 with SMTP id ne3so66456196wic.0 for ; Mon, 24 Aug 2015 02:42:10 -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=q+iOg5j53Bjyt7CSJKDOs9x8MFsbt1u9bQ4pdFIfEsc=; b=MThiYmOvdVLPsMaYcCG/DZ2prfLMzwRM088V0F6OpQBRZg6g/eqvmA7QSgbCugMc17 7Ll5ljRNckrVcLIH2F+qnXnppoTIJKksxsq5KHmDxPcouqathPOaiVeUkyue5yva6ZA7 +Cs7xrDNhYpXnxdSDaT4wR4EnsXYZ4FLTNLV4lbeac5eNNGdV0eg7jho+SUd68Wn8jUf cILXynXaxspy2XxW4ocIMuDr2JBhlsw9kaKMIz196Ab52UPsJsZ4Gv/j0xIFe70TTbjE ow9zpjZVnEKuVgjV0ua1izanrF/s/FjBDZoLxB1yjcN9N6PxHyO+5F4QmQufUQLCDoWf d3lA== X-Gm-Message-State: ALoCoQlgwNxh8zb9t3dXYEbm1pkGjvzRofpLzK+igRhUK1YIY+arGh0r/9GSHtIQQ1G6xAYMm74P X-Received: by 10.180.21.169 with SMTP id w9mr28386564wie.73.1440409330708; Mon, 24 Aug 2015 02:42:10 -0700 (PDT) Received: from lmenx315.st.com. ([80.12.55.183]) by smtp.gmail.com with ESMTPSA id ub19sm15309920wib.8.2015.08.24.02.42.08 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 24 Aug 2015 02:42:10 -0700 (PDT) From: Gabriel Fernandez To: Rob Herring , Pawel Moll , Mark Rutland , Ian Campbell , Kumar Gala , Srinivas Kandagatla , Maxime Coquelin , Patrice Chotard , Russell King , Michael Turquette , Stephen Boyd , Gabriel Fernandez , Peter Griffin , Pankaj Dev , Olivier Bideau , Geert Uytterhoeven , Fabian Frederick Subject: [PATCH v2 1/4] drivers: clk: st: Support for enable/disable in Clockgen PLLs Date: Mon, 24 Aug 2015 11:40:48 +0200 Message-Id: <1440409251-11166-2-git-send-email-gabriel.fernandez@linaro.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1440409251-11166-1-git-send-email-gabriel.fernandez@linaro.org> References: <1440409251-11166-1-git-send-email-gabriel.fernandez@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20150824_024232_632788_BD17B831 X-CRM114-Status: GOOD ( 17.77 ) 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, linux-clk@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, kernel@stlinux.com 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 The patch adds support for enable/disable of the Clockgen PLLs. clkgen_pll_enable/clkgen_pll_disable added as generic function for all PLLs. Signed-off-by: Pankaj Dev Signed-off-by: Gabriel Fernandez --- drivers/clk/st/clkgen-pll.c | 92 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 91 insertions(+), 1 deletion(-) diff --git a/drivers/clk/st/clkgen-pll.c b/drivers/clk/st/clkgen-pll.c index b2a332c..7ee485d 100644 --- a/drivers/clk/st/clkgen-pll.c +++ b/drivers/clk/st/clkgen-pll.c @@ -18,6 +18,7 @@ #include #include #include +#include #include "clkgen.h" @@ -43,6 +44,7 @@ static DEFINE_SPINLOCK(clkgena_c32_odf_lock); struct clkgen_pll_data { struct clkgen_field pdn_status; + struct clkgen_field pdn_ctrl; struct clkgen_field locked_status; struct clkgen_field mdiv; struct clkgen_field ndiv; @@ -62,6 +64,7 @@ static const struct clk_ops st_pll1200c32_ops; static const struct clkgen_pll_data st_pll1600c65_ax = { .pdn_status = CLKGEN_FIELD(0x0, 0x1, 19), + .pdn_ctrl = CLKGEN_FIELD(0x10, 0x1, 0), .locked_status = CLKGEN_FIELD(0x0, 0x1, 31), .mdiv = CLKGEN_FIELD(0x0, C65_MDIV_PLL1600_MASK, 0), .ndiv = CLKGEN_FIELD(0x0, C65_NDIV_MASK, 8), @@ -70,6 +73,7 @@ static const struct clkgen_pll_data st_pll1600c65_ax = { static const struct clkgen_pll_data st_pll800c65_ax = { .pdn_status = CLKGEN_FIELD(0x0, 0x1, 19), + .pdn_ctrl = CLKGEN_FIELD(0xC, 0x1, 1), .locked_status = CLKGEN_FIELD(0x0, 0x1, 31), .mdiv = CLKGEN_FIELD(0x0, C65_MDIV_PLL800_MASK, 0), .ndiv = CLKGEN_FIELD(0x0, C65_NDIV_MASK, 8), @@ -79,6 +83,7 @@ static const struct clkgen_pll_data st_pll800c65_ax = { static const struct clkgen_pll_data st_pll3200c32_a1x_0 = { .pdn_status = CLKGEN_FIELD(0x0, 0x1, 31), + .pdn_ctrl = CLKGEN_FIELD(0x18, 0x1, 0), .locked_status = CLKGEN_FIELD(0x4, 0x1, 31), .ndiv = CLKGEN_FIELD(0x0, C32_NDIV_MASK, 0x0), .idf = CLKGEN_FIELD(0x4, C32_IDF_MASK, 0x0), @@ -96,6 +101,7 @@ static const struct clkgen_pll_data st_pll3200c32_a1x_0 = { static const struct clkgen_pll_data st_pll3200c32_a1x_1 = { .pdn_status = CLKGEN_FIELD(0xC, 0x1, 31), + .pdn_ctrl = CLKGEN_FIELD(0x18, 0x1, 1), .locked_status = CLKGEN_FIELD(0x10, 0x1, 31), .ndiv = CLKGEN_FIELD(0xC, C32_NDIV_MASK, 0x0), .idf = CLKGEN_FIELD(0x10, C32_IDF_MASK, 0x0), @@ -114,6 +120,7 @@ static const struct clkgen_pll_data st_pll3200c32_a1x_1 = { /* 415 specific */ static const struct clkgen_pll_data st_pll3200c32_a9_415 = { .pdn_status = CLKGEN_FIELD(0x0, 0x1, 0), + .pdn_ctrl = CLKGEN_FIELD(0x0, 0x1, 0), .locked_status = CLKGEN_FIELD(0x6C, 0x1, 0), .ndiv = CLKGEN_FIELD(0x0, C32_NDIV_MASK, 9), .idf = CLKGEN_FIELD(0x0, C32_IDF_MASK, 22), @@ -125,6 +132,7 @@ static const struct clkgen_pll_data st_pll3200c32_a9_415 = { static const struct clkgen_pll_data st_pll3200c32_ddr_415 = { .pdn_status = CLKGEN_FIELD(0x0, 0x1, 0), + .pdn_ctrl = CLKGEN_FIELD(0x0, 0x1, 0), .locked_status = CLKGEN_FIELD(0x100, 0x1, 0), .ndiv = CLKGEN_FIELD(0x8, C32_NDIV_MASK, 0), .idf = CLKGEN_FIELD(0x0, C32_IDF_MASK, 25), @@ -137,7 +145,8 @@ static const struct clkgen_pll_data st_pll3200c32_ddr_415 = { }; static const struct clkgen_pll_data st_pll1200c32_gpu_415 = { - .pdn_status = CLKGEN_FIELD(0x144, 0x1, 3), + .pdn_status = CLKGEN_FIELD(0x4, 0x1, 0), + .pdn_ctrl = CLKGEN_FIELD(0x4, 0x1, 0), .locked_status = CLKGEN_FIELD(0x168, 0x1, 0), .ldf = CLKGEN_FIELD(0x0, C32_LDF_MASK, 3), .idf = CLKGEN_FIELD(0x0, C32_IDF_MASK, 0), @@ -149,6 +158,7 @@ static const struct clkgen_pll_data st_pll1200c32_gpu_415 = { /* 416 specific */ static const struct clkgen_pll_data st_pll3200c32_a9_416 = { .pdn_status = CLKGEN_FIELD(0x0, 0x1, 0), + .pdn_ctrl = CLKGEN_FIELD(0x0, 0x1, 0), .locked_status = CLKGEN_FIELD(0x6C, 0x1, 0), .ndiv = CLKGEN_FIELD(0x8, C32_NDIV_MASK, 0), .idf = CLKGEN_FIELD(0x0, C32_IDF_MASK, 25), @@ -160,6 +170,7 @@ static const struct clkgen_pll_data st_pll3200c32_a9_416 = { static const struct clkgen_pll_data st_pll3200c32_ddr_416 = { .pdn_status = CLKGEN_FIELD(0x0, 0x1, 0), + .pdn_ctrl = CLKGEN_FIELD(0x0, 0x1, 0), .locked_status = CLKGEN_FIELD(0x10C, 0x1, 0), .ndiv = CLKGEN_FIELD(0x8, C32_NDIV_MASK, 0), .idf = CLKGEN_FIELD(0x0, C32_IDF_MASK, 25), @@ -173,6 +184,7 @@ static const struct clkgen_pll_data st_pll3200c32_ddr_416 = { static const struct clkgen_pll_data st_pll1200c32_gpu_416 = { .pdn_status = CLKGEN_FIELD(0x8E4, 0x1, 3), + .pdn_ctrl = CLKGEN_FIELD(0x8E4, 0x1, 3), .locked_status = CLKGEN_FIELD(0x90C, 0x1, 0), .ldf = CLKGEN_FIELD(0x0, C32_LDF_MASK, 3), .idf = CLKGEN_FIELD(0x0, C32_IDF_MASK, 0), @@ -184,6 +196,7 @@ static const struct clkgen_pll_data st_pll1200c32_gpu_416 = { static const struct clkgen_pll_data st_pll3200c32_407_a0 = { /* 407 A0 */ .pdn_status = CLKGEN_FIELD(0x2a0, 0x1, 8), + .pdn_ctrl = CLKGEN_FIELD(0x2a0, 0x1, 8), .locked_status = CLKGEN_FIELD(0x2a0, 0x1, 24), .ndiv = CLKGEN_FIELD(0x2a4, C32_NDIV_MASK, 16), .idf = CLKGEN_FIELD(0x2a4, C32_IDF_MASK, 0x0), @@ -196,6 +209,7 @@ static const struct clkgen_pll_data st_pll3200c32_407_a0 = { static const struct clkgen_pll_data st_pll3200c32_cx_0 = { /* 407 C0 PLL0 */ .pdn_status = CLKGEN_FIELD(0x2a0, 0x1, 8), + .pdn_ctrl = CLKGEN_FIELD(0x2a0, 0x1, 8), .locked_status = CLKGEN_FIELD(0x2a0, 0x1, 24), .ndiv = CLKGEN_FIELD(0x2a4, C32_NDIV_MASK, 16), .idf = CLKGEN_FIELD(0x2a4, C32_IDF_MASK, 0x0), @@ -208,6 +222,7 @@ static const struct clkgen_pll_data st_pll3200c32_cx_0 = { static const struct clkgen_pll_data st_pll3200c32_cx_1 = { /* 407 C0 PLL1 */ .pdn_status = CLKGEN_FIELD(0x2c8, 0x1, 8), + .pdn_ctrl = CLKGEN_FIELD(0x2c8, 0x1, 8), .locked_status = CLKGEN_FIELD(0x2c8, 0x1, 24), .ndiv = CLKGEN_FIELD(0x2cc, C32_NDIV_MASK, 16), .idf = CLKGEN_FIELD(0x2cc, C32_IDF_MASK, 0x0), @@ -220,6 +235,7 @@ static const struct clkgen_pll_data st_pll3200c32_cx_1 = { static const struct clkgen_pll_data st_pll3200c32_407_a9 = { /* 407 A9 */ .pdn_status = CLKGEN_FIELD(0x1a8, 0x1, 0), + .pdn_ctrl = CLKGEN_FIELD(0x1a8, 0x1, 0), .locked_status = CLKGEN_FIELD(0x87c, 0x1, 0), .ndiv = CLKGEN_FIELD(0x1b0, C32_NDIV_MASK, 0), .idf = CLKGEN_FIELD(0x1a8, C32_IDF_MASK, 25), @@ -271,6 +287,71 @@ static int clkgen_pll_is_enabled(struct clk_hw *hw) return !poweroff; } +static int __clkgen_pll_enable(struct clk_hw *hw) +{ + struct clkgen_pll *pll = to_clkgen_pll(hw); + void __iomem *base = pll->regs_base; + struct clkgen_field *field = &pll->data->locked_status; + int ret = 0; + u32 reg; + + if (clkgen_pll_is_enabled(hw)) + return 0; + + CLKGEN_WRITE(pll, pdn_ctrl, 0); + + ret = readl_relaxed_poll_timeout(base + field->offset, reg, + !!((reg >> field->shift) & field->mask), 0, 10000); + + if (!ret) + pr_debug("%s:%s enabled\n", __clk_get_name(hw->clk), __func__); + + return ret; +} + +static int clkgen_pll_enable(struct clk_hw *hw) +{ + struct clkgen_pll *pll = to_clkgen_pll(hw); + unsigned long flags = 0; + int ret = 0; + + if (pll->lock) + spin_lock_irqsave(pll->lock, flags); + + ret = __clkgen_pll_enable(hw); + + if (pll->lock) + spin_unlock_irqrestore(pll->lock, flags); + + return ret; +} + +static void __clkgen_pll_disable(struct clk_hw *hw) +{ + struct clkgen_pll *pll = to_clkgen_pll(hw); + + if (!clkgen_pll_is_enabled(hw)) + return; + + CLKGEN_WRITE(pll, pdn_ctrl, 1); + + pr_debug("%s:%s disabled\n", __clk_get_name(hw->clk), __func__); +} + +static void clkgen_pll_disable(struct clk_hw *hw) +{ + struct clkgen_pll *pll = to_clkgen_pll(hw); + unsigned long flags = 0; + + if (pll->lock) + spin_lock_irqsave(pll->lock, flags); + + __clkgen_pll_disable(hw); + + if (pll->lock) + spin_unlock_irqrestore(pll->lock, flags); +} + static unsigned long recalc_stm_pll800c65(struct clk_hw *hw, unsigned long parent_rate) { @@ -372,21 +453,29 @@ static unsigned long recalc_stm_pll1200c32(struct clk_hw *hw, } static const struct clk_ops st_pll1600c65_ops = { + .enable = clkgen_pll_enable, + .disable = clkgen_pll_disable, .is_enabled = clkgen_pll_is_enabled, .recalc_rate = recalc_stm_pll1600c65, }; static const struct clk_ops st_pll800c65_ops = { + .enable = clkgen_pll_enable, + .disable = clkgen_pll_disable, .is_enabled = clkgen_pll_is_enabled, .recalc_rate = recalc_stm_pll800c65, }; static const struct clk_ops stm_pll3200c32_ops = { + .enable = clkgen_pll_enable, + .disable = clkgen_pll_disable, .is_enabled = clkgen_pll_is_enabled, .recalc_rate = recalc_stm_pll3200c32, }; static const struct clk_ops st_pll1200c32_ops = { + .enable = clkgen_pll_enable, + .disable = clkgen_pll_disable, .is_enabled = clkgen_pll_is_enabled, .recalc_rate = recalc_stm_pll1200c32, }; @@ -414,6 +503,7 @@ static struct clk * __init clkgen_pll_register(const char *parent_name, pll->data = pll_data; pll->regs_base = reg; pll->hw.init = &init; + pll->lock = lock; clk = clk_register(NULL, &pll->hw); if (IS_ERR(clk)) {