From patchwork Wed Apr 5 10:32:01 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Amit Pundir X-Patchwork-Id: 96815 Delivered-To: patch@linaro.org Received: by 10.140.89.233 with SMTP id v96csp196061qgd; Wed, 5 Apr 2017 03:33:33 -0700 (PDT) X-Received: by 10.99.146.7 with SMTP id o7mr28991983pgd.6.1491388413632; Wed, 05 Apr 2017 03:33:33 -0700 (PDT) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id f16si20271056pli.143.2017.04.05.03.33.32; Wed, 05 Apr 2017 03:33:33 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org; spf=pass (google.com: best guess record for domain of stable-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=stable-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S933470AbdDEKdb (ORCPT + 6 others); Wed, 5 Apr 2017 06:33:31 -0400 Received: from mail-pg0-f45.google.com ([74.125.83.45]:33752 "EHLO mail-pg0-f45.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S933163AbdDEKdZ (ORCPT ); Wed, 5 Apr 2017 06:33:25 -0400 Received: by mail-pg0-f45.google.com with SMTP id x125so6038470pgb.0 for ; Wed, 05 Apr 2017 03:32:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=vNWIVuOVGtJ5eowm9iarUdPiM95ki0Bbc3wJlQ3Bh1s=; b=ZIM26njM+j+m2if5rJgTXoAsqYGLDI5RdH5It3hz2MyPktjMLxIU1bNH1vNRA282bj EjtDLj2NHpg4PTL7Thv7nlFVw/W63JY54fxsMpFywTWglQmXX9suWCYMxzW9yYOAv1mT yKCO4fQu5EYCH4SBiefBhEJedkAMNZvfyn0I4= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=vNWIVuOVGtJ5eowm9iarUdPiM95ki0Bbc3wJlQ3Bh1s=; b=XF/nZamV0N8/0HfArCHVqASRWM05IBx8Gdk6dgKDWkM+dGvuGElVtsb+ZVlLw//i3J Lx2PegMXD1RUA07QWT71fMDT2o27ysoUrbUg7AV8P1rIsd4Sm1180aMAmbopoNSO4ta1 ChgkDsqJlDRmGRzfEPsN7SEWmGFYODBiRxU8AfpH8V+a9UUH6Jjd2lFijTNI8ismFLqq dtbIvRYoL//Hh9sISN3dlhJRcpVEAAH31+hEKVeEfiYKOsSTrIm1I2u7oa3x1lrqBXkk NBUgNthrunupfKIoI6nakjF6YPfALdQbxzpdmHXPEko0bpn9IlQq7Z8GU1ibOoIxRSav hZjA== X-Gm-Message-State: AFeK/H2ELTH3HgNfsHsjJs7VJ7y1TVEYbG/nzyMa/gSKto1SA2sMkHLHYBxqmet37M+PYuMn X-Received: by 10.99.39.70 with SMTP id n67mr29592785pgn.132.1491388367274; Wed, 05 Apr 2017 03:32:47 -0700 (PDT) Received: from localhost.localdomain ([106.51.240.246]) by smtp.gmail.com with ESMTPSA id a62sm36732075pgc.60.2017.04.05.03.32.45 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 05 Apr 2017 03:32:46 -0700 (PDT) From: Amit Pundir To: stable@vger.kernel.org Cc: gregkh@linuxfoundation.org, Boris Brezillon , Stephen Boyd Subject: [PATCH v2 for-4.9 09/32] clk: bcm: Support rate change propagation on bcm2835 clocks Date: Wed, 5 Apr 2017 16:02:01 +0530 Message-Id: <1491388344-13521-10-git-send-email-amit.pundir@linaro.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1491388344-13521-1-git-send-email-amit.pundir@linaro.org> References: <1491388344-13521-1-git-send-email-amit.pundir@linaro.org> Sender: stable-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: stable@vger.kernel.org From: Boris Brezillon Some peripheral clocks, like the VEC (Video EnCoder) clock need to be set to a precise rate (in our case 108MHz). With the current implementation, where peripheral clocks are not allowed to forward rate change requests to their parents, it is impossible to match this requirement unless the bootloader has configured things correctly, or a specific rate has been assigned through the DT (with the assigned-clk-rates property). Add a new field to struct bcm2835_clock_data to specify which parent clocks accept rate change propagation, and support set rate propagation in bcm2835_clock_determine_rate(). Signed-off-by: Boris Brezillon Reviewed-by: Eric Anholt Signed-off-by: Stephen Boyd (cherry picked from commit 155e8b3b0ee320ae866b97dd31eba8a1f080a772) Signed-off-by: Amit Pundir --- drivers/clk/bcm/clk-bcm2835.c | 67 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 63 insertions(+), 4 deletions(-) -- 2.7.4 diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c index 2acaa77..df96fe6 100644 --- a/drivers/clk/bcm/clk-bcm2835.c +++ b/drivers/clk/bcm/clk-bcm2835.c @@ -436,6 +436,9 @@ struct bcm2835_clock_data { const char *const *parents; int num_mux_parents; + /* Bitmap encoding which parents accept rate change propagation. */ + unsigned int set_rate_parent; + u32 ctl_reg; u32 div_reg; @@ -1017,10 +1020,60 @@ bcm2835_clk_is_pllc(struct clk_hw *hw) return strncmp(clk_hw_get_name(hw), "pllc", 4) == 0; } +static unsigned long bcm2835_clock_choose_div_and_prate(struct clk_hw *hw, + int parent_idx, + unsigned long rate, + u32 *div, + unsigned long *prate) +{ + struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw); + struct bcm2835_cprman *cprman = clock->cprman; + const struct bcm2835_clock_data *data = clock->data; + unsigned long best_rate; + u32 curdiv, mindiv, maxdiv; + struct clk_hw *parent; + + parent = clk_hw_get_parent_by_index(hw, parent_idx); + + if (!(BIT(parent_idx) & data->set_rate_parent)) { + *prate = clk_hw_get_rate(parent); + *div = bcm2835_clock_choose_div(hw, rate, *prate, true); + + return bcm2835_clock_rate_from_divisor(clock, *prate, + *div); + } + + if (data->frac_bits) + dev_warn(cprman->dev, + "frac bits are not used when propagating rate change"); + + /* clamp to min divider of 2 if we're dealing with a mash clock */ + mindiv = data->is_mash_clock ? 2 : 1; + maxdiv = BIT(data->int_bits) - 1; + + /* TODO: Be smart, and only test a subset of the available divisors. */ + for (curdiv = mindiv; curdiv <= maxdiv; curdiv++) { + unsigned long tmp_rate; + + tmp_rate = clk_hw_round_rate(parent, rate * curdiv); + tmp_rate /= curdiv; + if (curdiv == mindiv || + (tmp_rate > best_rate && tmp_rate <= rate)) + best_rate = tmp_rate; + + if (best_rate == rate) + break; + } + + *div = curdiv << CM_DIV_FRAC_BITS; + *prate = curdiv * best_rate; + + return best_rate; +} + static int bcm2835_clock_determine_rate(struct clk_hw *hw, struct clk_rate_request *req) { - struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw); struct clk_hw *parent, *best_parent = NULL; bool current_parent_is_pllc; unsigned long rate, best_rate = 0; @@ -1048,9 +1101,8 @@ static int bcm2835_clock_determine_rate(struct clk_hw *hw, if (bcm2835_clk_is_pllc(parent) && !current_parent_is_pllc) continue; - prate = clk_hw_get_rate(parent); - div = bcm2835_clock_choose_div(hw, req->rate, prate, true); - rate = bcm2835_clock_rate_from_divisor(clock, prate, div); + rate = bcm2835_clock_choose_div_and_prate(hw, i, req->rate, + &div, &prate); if (rate > best_rate && rate <= req->rate) { best_parent = parent; best_prate = prate; @@ -1262,6 +1314,13 @@ static struct clk_hw *bcm2835_register_clock(struct bcm2835_cprman *cprman, init.name = data->name; init.flags = data->flags | CLK_IGNORE_UNUSED; + /* + * Pass the CLK_SET_RATE_PARENT flag if we are allowed to propagate + * rate changes on at least of the parents. + */ + if (data->set_rate_parent) + init.flags |= CLK_SET_RATE_PARENT; + if (data->is_vpu_clock) { init.ops = &bcm2835_vpu_clock_clk_ops; } else {