From patchwork Thu Jul 9 11:57:40 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gabriel Fernandez X-Patchwork-Id: 50950 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-la0-f71.google.com (mail-la0-f71.google.com [209.85.215.71]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 549AC213FD for ; Thu, 9 Jul 2015 11:58:46 +0000 (UTC) Received: by laar3 with SMTP id r3sf74488477laa.1 for ; Thu, 09 Jul 2015 04:58:45 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:cc:subject :date:message-id:in-reply-to:references:sender:precedence:list-id :x-original-sender:x-original-authentication-results:mailing-list :list-post:list-help:list-archive:list-unsubscribe; bh=qKfLRK6k8RnZAg63/LqfiP44XcuPIUM5UefBIqL2kGo=; b=UEMGL4mVKKYx+Ca4VwkTm9AI1Yzs4GubNygUOU1moRweZ0Z3iWcVC8hPJBIbwG7hnk oGb+prge8RqSO9URrqJ0ti5LwDqc6Y87bHbDhuO68C8H+nRRDeGCM1BX45zzmuTnFmjm zD+CB/Cg3Fq2uRFSMQ4oyQI5OktoknqmVDDpb9CLyx57SkihRjEa2KXujmXdWUa7UsHW z8JPCxxaYFpIOWQbofbZe134QPDQPE9YVyluVkiqm+2p1lCk+Tc/10HjOnIZYjBCgCRD TD1wBthdI4NhfKUcXUiaHeP8j2d9ro/eeLnBHnK3EpOuVod+m/+CGwVI9MuXw0Mn48ja 7CTg== X-Gm-Message-State: ALoCoQm8yYiwSL8XLd42WSt6rjVW1lU7ePV04aqitH+NUr1+oMuLFKTfp5u8lfrW4oWLf3c9vVOh X-Received: by 10.194.5.229 with SMTP id v5mr7787447wjv.0.1436443125339; Thu, 09 Jul 2015 04:58:45 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.37.40 with SMTP id v8ls998935laj.88.gmail; Thu, 09 Jul 2015 04:58:45 -0700 (PDT) X-Received: by 10.152.87.13 with SMTP id t13mr14552635laz.66.1436443125141; Thu, 09 Jul 2015 04:58:45 -0700 (PDT) Received: from mail-lb0-f179.google.com (mail-lb0-f179.google.com. [209.85.217.179]) by mx.google.com with ESMTPS id yk6si4609490lbb.90.2015.07.09.04.58.44 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 09 Jul 2015 04:58:44 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.179 as permitted sender) client-ip=209.85.217.179; Received: by lbbpo10 with SMTP id po10so73627798lbb.3 for ; Thu, 09 Jul 2015 04:58:44 -0700 (PDT) X-Received: by 10.112.166.2 with SMTP id zc2mr14265458lbb.29.1436443124700; Thu, 09 Jul 2015 04:58:44 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.112.108.230 with SMTP id hn6csp616004lbb; Thu, 9 Jul 2015 04:58:43 -0700 (PDT) X-Received: by 10.70.39.74 with SMTP id n10mr30901877pdk.57.1436443122699; Thu, 09 Jul 2015 04:58:42 -0700 (PDT) Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id gm10si8905811pbd.144.2015.07.09.04.58.39; Thu, 09 Jul 2015 04:58:42 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753451AbbGIL6c (ORCPT + 29 others); Thu, 9 Jul 2015 07:58:32 -0400 Received: from mail-wg0-f41.google.com ([74.125.82.41]:35076 "EHLO mail-wg0-f41.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753181AbbGIL6C (ORCPT ); Thu, 9 Jul 2015 07:58:02 -0400 Received: by wgjx7 with SMTP id x7so221238651wgj.2 for ; Thu, 09 Jul 2015 04:58:01 -0700 (PDT) X-Received: by 10.181.12.20 with SMTP id em20mr35358056wid.28.1436443081521; Thu, 09 Jul 2015 04:58:01 -0700 (PDT) Received: from lmenx315.st.com. ([80.12.39.69]) by smtp.gmail.com with ESMTPSA id lz10sm8436503wjb.48.2015.07.09.04.57.57 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 09 Jul 2015 04:58:00 -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 Cc: devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, kernel@stlinux.com, linux-clk@vger.kernel.org Subject: [PATCH 3/3] drivers: clk: st: Correct the pll-type for A9 for stih418 Date: Thu, 9 Jul 2015 13:57:40 +0200 Message-Id: <1436443060-12866-4-git-send-email-gabriel.fernandez@linaro.org> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1436443060-12866-1-git-send-email-gabriel.fernandez@linaro.org> References: <1436443060-12866-1-git-send-email-gabriel.fernandez@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: list List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: gabriel.fernandez@linaro.org X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.217.179 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , Add support for new PLL-type for stih418 A9-PLL. Currently the 407_A9_PLL type being used, it is corrected with this patch 4600c28 PLL allows to reach higher frequencies so its programming algorithm is extended. Signed-off-by: Pankaj Dev Signed-off-by: Gabriel Fernandez --- .../devicetree/bindings/clock/st/st,clkgen-pll.txt | 1 + drivers/clk/st/clkgen-pll.c | 195 +++++++++++++++++++++ 2 files changed, 196 insertions(+) diff --git a/Documentation/devicetree/bindings/clock/st/st,clkgen-pll.txt b/Documentation/devicetree/bindings/clock/st/st,clkgen-pll.txt index efb51cf..19dc0ca 100644 --- a/Documentation/devicetree/bindings/clock/st/st,clkgen-pll.txt +++ b/Documentation/devicetree/bindings/clock/st/st,clkgen-pll.txt @@ -23,6 +23,7 @@ Required properties: "st,stih407-plls-c32-a9", "st,clkgen-plls-c32" "st,stih407-plls-c32-c0_0", "st,clkgen-plls-c32" "st,stih407-plls-c32-c0_1", "st,clkgen-plls-c32" + "st,stih418-plls-c28-a9", "st,clkgen-plls-c32" "st,stih415-gpu-pll-c32", "st,clkgengpu-pll-c32" "st,stih416-gpu-pll-c32", "st,clkgengpu-pll-c32" diff --git a/drivers/clk/st/clkgen-pll.c b/drivers/clk/st/clkgen-pll.c index 04d66ee1d..7062943 100644 --- a/drivers/clk/st/clkgen-pll.c +++ b/drivers/clk/st/clkgen-pll.c @@ -42,6 +42,13 @@ DEFINE_SPINLOCK(clkgen_a9_lock); #define C32_MAX_ODFS (4) +/* + * PLL configuration register bits for PLL4600 C28 + */ +#define C28_NDIV_MASK (0xff) +#define C28_IDF_MASK (0x7) +#define C28_ODF_MASK (0x3f) + struct clkgen_pll_data { struct clkgen_field pdn_status; struct clkgen_field pdn_ctrl; @@ -66,6 +73,7 @@ static const struct clk_ops st_pll800c65_ops; static const struct clk_ops stm_pll3200c32_ops; static const struct clk_ops stm_pll3200c32_a9_ops; static const struct clk_ops st_pll1200c32_ops; +static const struct clk_ops stm_pll4600c28_ops; static const struct clkgen_pll_data st_pll1600c65_ax = { .pdn_status = CLKGEN_FIELD(0x0, 0x1, 19), @@ -254,6 +262,22 @@ static const struct clkgen_pll_data st_pll3200c32_407_a9 = { .ops = &stm_pll3200c32_a9_ops, }; +static struct clkgen_pll_data st_pll4600c28_418_a9 = { + /* 418 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, C28_NDIV_MASK, 0), + .idf = CLKGEN_FIELD(0x1a8, C28_IDF_MASK, 25), + .num_odfs = 1, + .odf = { CLKGEN_FIELD(0x1b0, C28_ODF_MASK, 8) }, + .odf_gate = { CLKGEN_FIELD(0x1ac, 0x1, 28) }, + .switch2pll_en = true, + .switch2pll = CLKGEN_FIELD(0x1a4, 0x1, 1), + .lock = &clkgen_a9_lock, + .ops = &stm_pll4600c28_ops, +}; + /** * DOC: Clock Generated by PLL, rate set and enabled by bootloader * @@ -610,6 +634,164 @@ static unsigned long recalc_stm_pll1200c32(struct clk_hw *hw, return rate; } +/* PLL output structure + * FVCO >> /2 >> FVCOBY2 (no output) + * |> Divider (ODF) >> PHI + * + * FVCOby2 output = (input * 2 * NDIV) / IDF (assuming FRAC_CONTROL==L) + * + * Rules: + * 4Mhz <= INFF input <= 350Mhz + * 4Mhz <= INFIN (INFF / IDF) <= 50Mhz + * 19.05Mhz <= FVCOby2 output (PHI w ODF=1) <= 3000Mhz + * 1 <= i (register/dec value for IDF) <= 7 + * 8 <= n (register/dec value for NDIV) <= 246 + */ + +static int clk_pll4600c28_get_params(unsigned long input, unsigned long output, + struct stm_pll *pll) +{ + + unsigned long i, infin, n; + unsigned long deviation = ~0; + unsigned long new_freq, new_deviation; + + /* Output clock range: 19Mhz to 3000Mhz */ + if (output < 19000000 || output > 3000000000u) + return -EINVAL; + + /* For better jitter, IDF should be smallest + and NDIV must be maximum */ + for (i = 1; i <= 7 && deviation; i++) { + /* INFIN checks */ + infin = input / i; + if (infin < 4000000 || infin > 50000000) + continue; /* Invalid case */ + + n = output / (infin * 2); + if (n < 8 || n > 246) + continue; /* Invalid case */ + if (n < 246) + n++; /* To work around 'y' when n=x.y */ + + for (; n >= 8 && deviation; n--) { + new_freq = infin * 2 * n; + if (new_freq < output) + break; /* Optimization: shorting loop */ + + new_deviation = new_freq - output; + if (!new_deviation || new_deviation < deviation) { + pll->idf = i; + pll->ndiv = n; + deviation = new_deviation; + } + } + } + + if (deviation == ~0) /* No solution found */ + return -EINVAL; + + return 0; +} + +static int clk_pll4600c28_get_rate(unsigned long input, struct stm_pll *pll, + unsigned long *rate) +{ + if (!pll->idf) + pll->idf = 1; + + *rate = (input / pll->idf) * 2 * pll->ndiv; + + return 0; +} + +static unsigned long recalc_stm_pll4600c28(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct clkgen_pll *pll = to_clkgen_pll(hw); + struct stm_pll params; + unsigned long rate; + + if (!clkgen_pll_is_enabled(hw) || !clkgen_pll_is_locked(hw)) + return 0; + + params.ndiv = CLKGEN_READ(pll, ndiv); + params.idf = CLKGEN_READ(pll, idf); + + clk_pll4600c28_get_rate(parent_rate, ¶ms, &rate); + + pr_debug("%s:%s rate %lu\n", __clk_get_name(hw->clk), __func__, rate); + + return rate; +} + +static long round_rate_stm_pll4600c28(struct clk_hw *hw, unsigned long rate, + unsigned long *prate) +{ + struct stm_pll params; + + if (!clk_pll4600c28_get_params(*prate, rate, ¶ms)) { + clk_pll4600c28_get_rate(*prate, ¶ms, &rate); + } else { + pr_debug("%s: %s rate %ld Invalid\n", __func__, + __clk_get_name(hw->clk), rate); + return 0; + } + + pr_debug("%s: %s new rate %ld [ndiv=%u] [idf=%u]\n", + __func__, __clk_get_name(hw->clk), + rate, (unsigned int)params.ndiv, + (unsigned int)params.idf); + + return rate; +} + +static int set_rate_stm_pll4600c28(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct clkgen_pll *pll = to_clkgen_pll(hw); + struct stm_pll params; + long hwrate; + unsigned long flags = 0; + + if (!rate || !parent_rate) + return -EINVAL; + + if (!clk_pll4600c28_get_params(parent_rate, rate, ¶ms)) { + clk_pll4600c28_get_rate(parent_rate, ¶ms, &hwrate); + } else { + pr_debug("%s: %s rate %ld Invalid\n", __func__, + __clk_get_name(hw->clk), rate); + return -EINVAL; + } + + pr_debug("%s: %s new rate %ld [ndiv=0x%x] [idf=0x%x]\n", + __func__, __clk_get_name(hw->clk), + hwrate, (unsigned int)params.ndiv, + (unsigned int)params.idf); + + if (!hwrate) + return -EINVAL; + + pll->ndiv = params.ndiv; + pll->idf = params.idf; + + clkgen_pll_disable(hw); + + if (pll->lock) + spin_lock_irqsave(pll->lock, flags); + + CLKGEN_WRITE(pll, ndiv, pll->ndiv); + CLKGEN_WRITE(pll, idf, pll->idf); + + if (pll->lock) + spin_unlock_irqrestore(pll->lock, flags); + + clkgen_pll_enable(hw); + + return 0; +} + static const struct clk_ops st_pll1600c65_ops = { .enable = clkgen_pll_enable, .disable = clkgen_pll_disable, @@ -647,6 +829,15 @@ static const struct clk_ops st_pll1200c32_ops = { .recalc_rate = recalc_stm_pll1200c32, }; +static const struct clk_ops stm_pll4600c28_ops = { + .enable = clkgen_pll_enable, + .disable = clkgen_pll_disable, + .is_enabled = clkgen_pll_is_enabled, + .recalc_rate = recalc_stm_pll4600c28, + .round_rate = round_rate_stm_pll4600c28, + .set_rate = set_rate_stm_pll4600c28, +}; + static struct clk * __init clkgen_pll_register(const char *parent_name, struct clkgen_pll_data *pll_data, void __iomem *reg, @@ -892,6 +1083,10 @@ static const struct of_device_id c32_pll_of_match[] = { .compatible = "st,stih407-plls-c32-a9", .data = &st_pll3200c32_407_a9, }, + { + .compatible = "st,stih418-plls-c28-a9", + .data = &st_pll4600c28_418_a9, + }, {} };