From patchwork Mon Aug 24 09:40:50 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gabriel Fernandez X-Patchwork-Id: 52630 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-la0-f72.google.com (mail-la0-f72.google.com [209.85.215.72]) by patches.linaro.org (Postfix) with ESMTPS id 36F542041A for ; Mon, 24 Aug 2015 09:43:31 +0000 (UTC) Received: by labia3 with SMTP id ia3sf13636869lab.3 for ; Mon, 24 Aug 2015 02:43:30 -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=3M3VZaJqUmYWmWOEiKOzC0RkLG+Ac1MUMZqVdifaYB8=; b=X0EFlqaHzI4WlEDXF4+uJkpIx+fohB1VJ5CEkxg06VVJfbGpYTNQng+BsBFf7lAyYK CkC03J71SukCt7qor42DuNH/KlTwo3KDEuenzYV6hhPDkWMzKIrTwrnUmOpgmTzBAKPg Bhz7qO6GgD6hLcM9YC/EUhZ5+cKDXRb/QQ2l5M1+phV8U9xAT0xUt3ejBNgPiKTtgPes n9xu/2/+d0BfdTJtPNVyBJTNBZ33kOD2VBA8O4FOtGPu10vhkVO2HG4a4PUOJSHHKsmm XZrz6vAbtgFw/sy0m9MXJ6wivIg4q2YOwdBPyJmi+fD0mLlFaA83kIlhNNb6rM5mYuIm lrYQ== X-Gm-Message-State: ALoCoQk6IKx8xbfSuWKhbD8i/ty6TjLwn4BK85H6PxotY48QkCrH/OQwsITAhQbJ1rmNid5udini X-Received: by 10.112.17.106 with SMTP id n10mr6559634lbd.18.1440409410054; Mon, 24 Aug 2015 02:43:30 -0700 (PDT) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.152.21.100 with SMTP id u4ls23286lae.51.gmail; Mon, 24 Aug 2015 02:43:29 -0700 (PDT) X-Received: by 10.152.18.137 with SMTP id w9mr19343699lad.23.1440409409872; Mon, 24 Aug 2015 02:43:29 -0700 (PDT) Received: from mail-la0-f51.google.com (mail-la0-f51.google.com. [209.85.215.51]) by mx.google.com with ESMTPS id rz7si12675184lbb.129.2015.08.24.02.43.29 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 24 Aug 2015 02:43:29 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.215.51 as permitted sender) client-ip=209.85.215.51; Received: by laba3 with SMTP id a3so73884454lab.1 for ; Mon, 24 Aug 2015 02:43:29 -0700 (PDT) X-Received: by 10.112.199.133 with SMTP id jk5mr19867903lbc.32.1440409409773; Mon, 24 Aug 2015 02:43:29 -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.162.200 with SMTP id yc8csp2346519lbb; Mon, 24 Aug 2015 02:43:28 -0700 (PDT) X-Received: by 10.68.191.130 with SMTP id gy2mr44244545pbc.124.1440409408373; Mon, 24 Aug 2015 02:43:28 -0700 (PDT) Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id ja7si26526916pbd.169.2015.08.24.02.43.26; Mon, 24 Aug 2015 02:43:28 -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 S933594AbbHXJnY (ORCPT + 28 others); Mon, 24 Aug 2015 05:43:24 -0400 Received: from mail-wi0-f169.google.com ([209.85.212.169]:38753 "EHLO mail-wi0-f169.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933344AbbHXJmR (ORCPT ); Mon, 24 Aug 2015 05:42:17 -0400 Received: by wicja10 with SMTP id ja10so66598684wic.1 for ; Mon, 24 Aug 2015 02:42:16 -0700 (PDT) X-Received: by 10.194.172.233 with SMTP id bf9mr38749020wjc.107.1440409336288; Mon, 24 Aug 2015 02:42:16 -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.13 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 24 Aug 2015 02:42:15 -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 v2 3/4] drivers: clk: st: Correct the pll-type for A9 for stih418 Date: Mon, 24 Aug 2015 11:40:50 +0200 Message-Id: <1440409251-11166-4-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> 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.215.51 as permitted sender) smtp.mailfrom=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 | 194 +++++++++++++++++++++ 2 files changed, 195 insertions(+) diff --git a/Documentation/devicetree/bindings/clock/st/st,clkgen-pll.txt b/Documentation/devicetree/bindings/clock/st/st,clkgen-pll.txt index e2c6db0..8f84c81 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,plls-c32-cx_0", "st,clkgen-plls-c32" "st,plls-c32-cx_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 94e5a0b..3eb4ffb 100644 --- a/drivers/clk/st/clkgen-pll.c +++ b/drivers/clk/st/clkgen-pll.c @@ -44,6 +44,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; @@ -68,6 +75,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), @@ -256,6 +264,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 * @@ -611,6 +635,163 @@ 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, @@ -648,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, @@ -893,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, + }, {} };