From patchwork Tue Jul 25 07:37:07 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Quentin Schulz X-Patchwork-Id: 108624 Delivered-To: patch@linaro.org Received: by 10.140.101.44 with SMTP id t41csp261124qge; Tue, 25 Jul 2017 00:42:28 -0700 (PDT) X-Received: by 10.84.133.193 with SMTP id f59mr20349070plf.316.1500968548833; Tue, 25 Jul 2017 00:42:28 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1500968548; cv=none; d=google.com; s=arc-20160816; b=zciP/LTz0/cmscqF17UQ+mFaYXaZ8Nu0kJrbw//pwZt2cHXWGjMSVhI7ZJfnfmCelD TqUWHBWq84drzjB4O79y1dJbKNp5TEIS2+AbuLZs+Dbcut0k28hhjvLFTeVsDrhdEP63 46pzasPUZXy9dKebgKKfWX7vMPqYUFKdqY/zwExH808i6W6TkYxNg6FPJnjT6kSjjx1J DPU4+h89UrWDn9DOpNjqHClMpMvDXn1b+JiVuQPO+DnRShoHowJWHYswxIv+4meNXn6R OO5i+suPieWHdtQiJm5LTGpjtdl3qYD8FVVCMW4WWBGMKpu6vyEuc26kjfMBcjsSDyw4 SDRQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:references :in-reply-to:message-id:date:subject:cc:to:from :arc-authentication-results; bh=mXU+vWE0duksLnHl0jLAwjM+s2PespJF7/yCWH+qICs=; b=h5eV/Zptt9AUQIIb5d0gLqNk5nhFfQXfpxf843FBCI2KwL5CO5IvHoKsnhBCLDw7sa 1qKPXkSOuDN8g6g73hgtsZy9LYgIi/O5Po3JU2gy3axQFvGN/yaSzKA/DDjuoGxisfFw FziIY8JauCXsBFBSXL4ctXsbNfK44h4N8KmzfLyE9PZaK9rIfPHVZAK3LmUu8g5r5X+n q6dHWy4YL/UrG0MplcM3wm4gqGWxwM+m35ImpGgxqUGDkWwsY2tYrO0eegCjZqtKA6FP kip6ID3NS/hCLb8W46f8eC/BmkO2RXgCWUItfow6wOQQ4LMiieUMBxuWn9L/UiNcE75a bmJw== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id a1si7713820pfb.610.2017.07.25.00.42.28; Tue, 25 Jul 2017 00:42: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; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751714AbdGYHmN (ORCPT + 26 others); Tue, 25 Jul 2017 03:42:13 -0400 Received: from mail.free-electrons.com ([62.4.15.54]:42368 "EHLO mail.free-electrons.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751530AbdGYHlP (ORCPT ); Tue, 25 Jul 2017 03:41:15 -0400 Received: by mail.free-electrons.com (Postfix, from userid 110) id C693A21DFE; Tue, 25 Jul 2017 09:41:12 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on mail.free-electrons.com X-Spam-Level: X-Spam-Status: No, score=-1.0 required=5.0 tests=ALL_TRUSTED,SHORTCIRCUIT, URIBL_BLOCKED shortcircuit=ham autolearn=disabled version=3.4.0 Received: from localhost.localdomain (LStLambert-657-1-97-87.w90-63.abo.wanadoo.fr [90.63.216.87]) by mail.free-electrons.com (Postfix) with ESMTPSA id 32AED21D43; Tue, 25 Jul 2017 09:40:54 +0200 (CEST) From: Quentin Schulz To: mturquette@baylibre.com, sboyd@codeaurora.org, robh+dt@kernel.org, mark.rutland@arm.com, lgirdwood@gmail.com, broonie@kernel.org, nicolas.ferre@microchip.com, alexandre.belloni@free-electrons.com, linux@armlinux.org.uk, boris.brezillon@free-electrons.com, perex@perex.cz, tiwai@suse.com Cc: cyrille.pitchen@wedev4u.fr, thomas.petazzoni@free-electrons.com, linux-clk@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, alsa-devel@alsa-project.org, linux-arm-kernel@lists.infradead.org, Quentin Schulz Subject: [PATCH v4 6/9] clk: at91: clk-generated: make gclk determine audio_pll rate Date: Tue, 25 Jul 2017 09:37:07 +0200 Message-Id: <4ccbc456b4812f4e91cc446914759781e6933a48.1500968090.git-series.quentin.schulz@free-electrons.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: References: In-Reply-To: References: Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org This allows gclk to determine audio_pll rate and set the parent rate accordingly. However, there are multiple children clocks that could technically change the rate of audio_pll (via gck). With the rate locking, the first consumer to enable the clock will be the one definitely setting the rate of the clock. Since audio IPs are most likely to request the same rate, we enforce that the only clks able to modify gck rate are those of audio IPs. To remain consistent, we deny other clocks to be children of audio_pll. Signed-off-by: Quentin Schulz Acked-by: Boris Brezillon --- drivers/clk/at91/clk-generated.c | 63 +++++++++++++++++++++++++++++---- 1 file changed, 57 insertions(+), 6 deletions(-) -- git-series 0.9.1 diff --git a/drivers/clk/at91/clk-generated.c b/drivers/clk/at91/clk-generated.c index 7260e49..3348136 100644 --- a/drivers/clk/at91/clk-generated.c +++ b/drivers/clk/at91/clk-generated.c @@ -26,6 +26,13 @@ #define GENERATED_SOURCE_MAX 6 #define GENERATED_MAX_DIV 255 +#define GCK_ID_SSC0 43 +#define GCK_ID_SSC1 44 +#define GCK_ID_I2S0 54 +#define GCK_ID_I2S1 55 +#define GCK_ID_CLASSD 59 +#define GCK_INDEX_DT_AUDIO_PLL 5 + struct clk_generated { struct clk_hw hw; struct regmap *regmap; @@ -34,6 +41,7 @@ struct clk_generated { u32 id; u32 gckdiv; u8 parent_id; + bool audio_pll_allowed; }; #define to_clk_generated(hw) \ @@ -126,15 +134,14 @@ static int clk_generated_determine_rate(struct clk_hw *hw, { struct clk_generated *gck = to_clk_generated(hw); struct clk_hw *parent = NULL; + struct clk_rate_request req_parent = *req; long best_rate = -EINVAL; - unsigned long min_rate; + unsigned long min_rate, parent_rate; int best_diff = -1; int i; + u32 div; - for (i = 0; i < clk_hw_get_num_parents(hw); i++) { - u32 div; - unsigned long parent_rate; - + for (i = 0; i < clk_hw_get_num_parents(hw) - 1; i++) { parent = clk_hw_get_parent_by_index(hw, i); if (!parent) continue; @@ -150,11 +157,38 @@ static int clk_generated_determine_rate(struct clk_hw *hw, clk_generated_best_diff(req, parent, parent_rate, div, &best_diff, &best_rate); + if (!best_diff) + break; + } + + /* + * The audio_pll rate can be modified, unlike the five others clocks + * that should never be altered. + * The audio_pll can technically be used by multiple consumers. However, + * with the rate locking, the first consumer to enable to clock will be + * the one definitely setting the rate of the clock. + * Since audio IPs are most likely to request the same rate, we enforce + * that the only clks able to modify gck rate are those of audio IPs. + */ + + if (!gck->audio_pll_allowed) + goto end; + + parent = clk_hw_get_parent_by_index(hw, GCK_INDEX_DT_AUDIO_PLL); + if (!parent) + goto end; + + for (div = 1; div < GENERATED_MAX_DIV + 2; div++) { + req_parent.rate = req->rate * div; + __clk_determine_rate(parent, &req_parent); + clk_generated_best_diff(req, parent, req_parent.rate, div, + &best_diff, &best_rate); if (!best_diff) break; } +end: pr_debug("GCLK: %s, best_rate = %ld, parent clk: %s @ %ld\n", __func__, best_rate, __clk_get_name((req->best_parent_hw)->clk), @@ -264,7 +298,8 @@ at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock, init.ops = &generated_ops; init.parent_names = parent_names; init.num_parents = num_parents; - init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE; + init.flags = CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE | + CLK_SET_RATE_PARENT; gck->id = id; gck->hw.init = &init; @@ -296,6 +331,7 @@ static void __init of_sama5d2_clk_generated_setup(struct device_node *np) struct device_node *gcknp; struct clk_range range = CLK_RANGE(0, 0); struct regmap *regmap; + struct clk_generated *gck; num_parents = of_clk_get_parent_count(np); if (num_parents == 0 || num_parents > GENERATED_SOURCE_MAX) @@ -327,6 +363,21 @@ static void __init of_sama5d2_clk_generated_setup(struct device_node *np) hw = at91_clk_register_generated(regmap, &pmc_pcr_lock, name, parent_names, num_parents, id, &range); + + gck = to_clk_generated(hw); + + if (of_device_is_compatible(np, + "atmel,sama5d2-clk-generated")) { + if (gck->id == GCK_ID_SSC0 || gck->id == GCK_ID_SSC1 || + gck->id == GCK_ID_I2S0 || gck->id == GCK_ID_I2S1 || + gck->id == GCK_ID_CLASSD) + gck->audio_pll_allowed = true; + else + gck->audio_pll_allowed = false; + } else { + gck->audio_pll_allowed = false; + } + if (IS_ERR(hw)) continue;