From patchwork Tue Nov 4 07:52:38 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kever Yang X-Patchwork-Id: 5223511 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id B49D49F295 for ; Tue, 4 Nov 2014 07:57:36 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id B78072012B for ; Tue, 4 Nov 2014 07:57:35 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id CA1FD20108 for ; Tue, 4 Nov 2014 07:57:34 +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 1XlYy5-00063x-Rz; Tue, 04 Nov 2014 07:55:57 +0000 Received: from mail-pd0-x22d.google.com ([2607:f8b0:400e:c02::22d]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1XlYxw-0005ki-3w; Tue, 04 Nov 2014 07:55:48 +0000 Received: by mail-pd0-f173.google.com with SMTP id v10so13163839pde.4 for ; Mon, 03 Nov 2014 23:55:26 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=+gGmReuuG1uBYGip95fNjy7orov3guWD99HGNW/q5bc=; b=PYuwWD4WiOV3p2ELAJHaWnd8NKf2V0UW9wRQu14wIyRsYjWGfjkFMj83NUzOyURurF P5LaLMp4KbD6Tja1ZXA6gaJg5SyhiFG7tHuDQpfgfg9HkKD0I+8zF1LehPDN9vok9arS yDDpIsvo0My1M8C9m9XikVpMpFHMOdg738rRnaCRZnKxv7S54Tr+I015ysKQcxMNlKUv Zz9ENF+VE2eI9gOk93/u+2SlDpUamzkQMs1xDxYy63SYTP+2u6VJYV6eSRbLPtd/ZG1u 6h0j7wbJ2AwHdSIeq9WdnKvntbZHi+uTqH07Tn3lEggBSUn6tcgVZMUjtm+J6JlQW9bm YW6Q== X-Received: by 10.70.19.206 with SMTP id h14mr6351207pde.49.1415087726701; Mon, 03 Nov 2014 23:55:26 -0800 (PST) Received: from localhost.localdomain ([58.22.7.114]) by mx.google.com with ESMTPSA id r4sm16197953pdm.93.2014.11.03.23.55.19 for (version=TLSv1.2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 03 Nov 2014 23:55:25 -0800 (PST) From: Kever Yang To: Mike Turquette , Heiko Stuebner Subject: [PATCH 4/5] clk: rockchip: add the vop_determine_rate for vop dclock Date: Tue, 4 Nov 2014 15:52:38 +0800 Message-Id: <1415087559-19444-5-git-send-email-kever.yang@rock-chips.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1415087559-19444-1-git-send-email-kever.yang@rock-chips.com> References: <1415087559-19444-1-git-send-email-kever.yang@rock-chips.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20141103_235548_306225_98FF1573 X-CRM114-Status: GOOD ( 20.21 ) X-Spam-Score: 1.0 (+) Cc: huangtao@rock-chips.com, dkl@rock-chips.com, addy.ke@rock-chips.com, yzq@rock-chips.com, linux-kernel@vger.kernel.org, dianders@chromium.org, Kever Yang , linux-rockchip@lists.infradead.org, fzf@rock-chips.com, ykk@rock-chips.com, cf@rock-chips.com, sonnyrao@chromium.org, linux-arm-kernel@lists.infradead.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.18-1 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , 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=-0.7 required=5.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_NONE, RP_MATCHES_RCVD, T_DKIM_INVALID, UNPARSEABLE_RELAY, URIBL_BLACK autolearn=no 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 Rk3288 has 5 PLLs(APLL, DPLL, CPLL, GPLL, NPLL), APLL is for CPU clock only and DPLL is for DRAM clock only, and other 3 PLls used for all other peripherals. We have to make a total solution for how to campatible all kinds of clock requirement by on chip peripheral controllers. Some controllers like I2S and HDMI need accurate frequency while others controllers accept clock rate with margin. According to our experience on rk3288, we prefer to use CPLL and GPLL fixed at 400MHz and 594MHz for general use for most peripheral. The fraction divider should be enough for I2S controller. The HDMI is the most diffical one if we have to support all the resolution requirement for frequency. Most people use 720p and 1080 i/p resolution with 74.25MHz/148.5MHz, which can get clock rate from 594MHz(maybe from GPLL). some other resolution like 640*480 will use 25.175MHz, which is hard to get from general used PLLs. So it is better to make HDMI controller has the right to change the PLL frequency and get the clock rate it wants. We set NPLL to 500MHz as default, if HDMI can get what it need from existent clock provider, then change its divider and switch to that parent; if not, we have to change the NPLL's output and always make CPLL&GPLL not change. This patch add vop_determinate_rate as a div_ops to handle the HDMI clock things. Signed-off-by: Kever Yang --- drivers/clk/rockchip/clk-rk3288.c | 69 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c index 48412e9..0151140 100644 --- a/drivers/clk/rockchip/clk-rk3288.c +++ b/drivers/clk/rockchip/clk-rk3288.c @@ -14,6 +14,7 @@ */ #include +#include #include #include #include @@ -25,6 +26,7 @@ enum rk3288_plls { apll, dpll, cpll, gpll, npll, }; +const struct clk_ops dclk_vop_ops; struct rockchip_pll_rate_table rk3288_pll_rates[] = { RK3066_PLL_RATE(2208000000, 1, 92, 1), @@ -766,6 +768,73 @@ static const char *rk3288_critical_clocks[] __initconst = { "aclk_peri", "hclk_peri", }; +#define DCLK_VOP_PARENT_NPLL 2 + +long dclk_vop_determine_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *best_parent_rate, + struct clk **best_parent_p) +{ + struct clk *clk = hw->clk, *parent; + unsigned long parent_rate, best = 0; + int num_parents = clk->num_parents; + int i; + + /* + * check if one of the generic plls can provide a cleanly dividable + * rate without changing them. + */ + for (i = 0; i < (num_parents - 1); i++) { + parent = clk_get_parent_by_index(clk, i); + parent_rate = __clk_get_rate(parent); + if (parent_rate % rate == 0) { + *best_parent_p = parent; + *best_parent_rate = parent_rate; + return rate; + } + } + + /* take the npll and set its rate to something suitable */ + for (i = 0; rk3288_pll_rates[i].rate != 0; i++) { + if (rk3288_pll_rates[i].rate % rate == 0) { + *best_parent_p = clk_get_parent_by_index(clk, + DCLK_VOP_PARENT_NPLL); + *best_parent_rate = rk3288_pll_rates[i].rate; + return rk3288_pll_rates[i].rate; + } + } + + /* + * We were not able to find a matching rate, so falling back + * to finding the fastest rate < rate. + * We allow the npll to change its rate while the other plls + * are not allowed to change. + */ + for (i = 0; i < num_parents; i++) { + parent = clk_get_parent_by_index(clk, i); + if (!parent) + continue; + + if (i == DCLK_VOP_PARENT_NPLL) + parent_rate = __clk_round_rate(parent, rate); + else + parent_rate = __clk_get_rate(parent); + if (parent_rate <= rate && parent_rate > best) { + int div = DIV_ROUND_UP(parent_rate, rate); + *best_parent_p = parent; + *best_parent_rate = parent_rate; + best = DIV_ROUND_UP(parent_rate, div); + } + } + + return best; +} + + +const struct clk_ops dclk_vop_ops = { + .recalc_rate = clk_divider_recalc_rate, + .set_rate = clk_divider_set_rate, + .determine_rate = dclk_vop_determine_rate, +}; static void __init rk3288_clk_init(struct device_node *np) {