From patchwork Tue Apr 9 13:48:02 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Emilio_L=C3=B3pez?= X-Patchwork-Id: 235088 Return-Path: X-Original-To: incoming-imx@patchwork.ozlabs.org Delivered-To: patchwork-incoming-imx@bilbo.ozlabs.org Received: from casper.infradead.org (casper.infradead.org [IPv6:2001:770:15f::2]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 4BA792C0092 for ; Tue, 9 Apr 2013 23:51:13 +1000 (EST) Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1UPYwG-0006EL-Ji; Tue, 09 Apr 2013 13:50:20 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1UPYw3-0003IT-BX; Tue, 09 Apr 2013 13:50:07 +0000 Received: from [2606:3f00:60:21c:d00d:c0de:4:f00d] (helo=zetta.elopez.com.ar) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1UPYvu-0003HN-FC for linux-arm-kernel@lists.infradead.org; Tue, 09 Apr 2013 13:50:00 +0000 Received: from 201-212-118-238.prima.net.ar ([201.212.118.238] helo=desktop.lan) by zetta.elopez.com.ar with esmtpsa (TLS1.2:DHE_RSA_AES_256_CBC_SHA256:256) (Exim 4.80) id 1UPYvr-0007iA-7k; Tue, 09 Apr 2013 10:49:55 -0300 From: =?UTF-8?q?Emilio=20L=C3=B3pez?= To: Maxime Ripard , Mike Turquette , Prashant Gaikwad Subject: [PATCH 1/3] clk: composite: Add fixed-rate support Date: Tue, 9 Apr 2013 10:48:02 -0300 Message-Id: <1365515284-32061-2-git-send-email-emilio@elopez.com.ar> X-Mailer: git-send-email 1.8.2.1 In-Reply-To: <1365515284-32061-1-git-send-email-emilio@elopez.com.ar> References: <1365515284-32061-1-git-send-email-emilio@elopez.com.ar> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130409_094958_637146_6D51B2D8 X-CRM114-Status: GOOD ( 11.94 ) X-Spam-Score: -1.1 (-) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-1.1 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 SPF_PASS SPF: sender matches SPF record -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] 0.8 RDNS_NONE Delivered to internal network by a host with no rDNS Cc: Gregory CLEMENT , =?UTF-8?q?Emilio=20L=C3=B3pez?= , linux-arm-kernel@lists.infradead.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+incoming-imx=patchwork.ozlabs.org@lists.infradead.org List-Id: linux-imx-kernel.lists.patchwork.ozlabs.org This patchset adds fixed-rate support to the composite clock, allowing us to register gatable oscillators. Signed-off-by: Emilio López --- drivers/clk/clk-composite.c | 57 ++++++++++++++++++++++++++++++++++++++++---- include/linux/clk-provider.h | 6 +++++ 2 files changed, 59 insertions(+), 4 deletions(-) diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c index 097dee4..5416e1d 100644 --- a/drivers/clk/clk-composite.c +++ b/drivers/clk/clk-composite.c @@ -43,8 +43,8 @@ static int clk_composite_set_parent(struct clk_hw *hw, u8 index) return mux_ops->set_parent(mux_hw, index); } -static unsigned long clk_composite_recalc_rate(struct clk_hw *hw, - unsigned long parent_rate) +static unsigned long clk_composite_recalc_rate_div(struct clk_hw *hw, + unsigned long parent_rate) { struct clk_composite *composite = to_clk_composite(hw); const struct clk_ops *div_ops = composite->div_ops; @@ -55,6 +55,18 @@ static unsigned long clk_composite_recalc_rate(struct clk_hw *hw, return div_ops->recalc_rate(div_hw, parent_rate); } +static unsigned long clk_composite_recalc_rate_fixed(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct clk_composite *composite = to_clk_composite(hw); + const struct clk_ops *fixed_ops = composite->fixed_ops; + struct clk_hw *fixed_hw = composite->fixed_hw; + + fixed_hw->clk = hw->clk; + + return fixed_ops->recalc_rate(fixed_hw, parent_rate); +} + static long clk_composite_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *prate) { @@ -112,11 +124,12 @@ static void clk_composite_disable(struct clk_hw *hw) gate_ops->disable(gate_hw); } -struct clk *clk_register_composite(struct device *dev, const char *name, +static struct clk *_clk_register_composite(struct device *dev, const char *name, const char **parent_names, int num_parents, struct clk_hw *mux_hw, const struct clk_ops *mux_ops, struct clk_hw *div_hw, const struct clk_ops *div_ops, struct clk_hw *gate_hw, const struct clk_ops *gate_ops, + struct clk_hw *fixed_hw, const struct clk_ops *fixed_ops, unsigned long flags) { struct clk *clk; @@ -158,7 +171,7 @@ struct clk *clk_register_composite(struct device *dev, const char *name, composite->div_hw = div_hw; composite->div_ops = div_ops; - clk_composite_ops->recalc_rate = clk_composite_recalc_rate; + clk_composite_ops->recalc_rate = clk_composite_recalc_rate_div; clk_composite_ops->round_rate = clk_composite_round_rate; clk_composite_ops->set_rate = clk_composite_set_rate; } @@ -177,6 +190,17 @@ struct clk *clk_register_composite(struct device *dev, const char *name, clk_composite_ops->disable = clk_composite_disable; } + if (fixed_hw && fixed_ops) { + if (!fixed_ops->recalc_rate) { + clk = ERR_PTR(-EINVAL); + goto err; + } + + composite->fixed_hw = fixed_hw; + composite->fixed_ops = fixed_ops; + clk_composite_ops->recalc_rate = clk_composite_recalc_rate_fixed; + } + init.ops = clk_composite_ops; composite->hw.init = &init; @@ -193,9 +217,34 @@ struct clk *clk_register_composite(struct device *dev, const char *name, if (composite->gate_hw) composite->gate_hw->clk = clk; + if (composite->fixed_hw) + composite->fixed_hw->clk = clk; + return clk; err: kfree(composite); return clk; } + +struct clk *clk_register_composite(struct device *dev, const char *name, + const char **parent_names, int num_parents, + struct clk_hw *mux_hw, const struct clk_ops *mux_ops, + struct clk_hw *div_hw, const struct clk_ops *div_ops, + struct clk_hw *gate_hw, const struct clk_ops *gate_ops, + unsigned long flags) +{ + return _clk_register_composite(dev, name, parent_names, num_parents, + mux_hw, mux_ops, div_hw, div_ops, + gate_hw, gate_ops, NULL, NULL, flags); +} + +struct clk *clk_register_gatable_osc(struct device *dev, const char *name, + struct clk_hw *fixed_hw, const struct clk_ops *fixed_ops, + struct clk_hw *gate_hw, const struct clk_ops *gate_ops, + unsigned long flags) +{ + return _clk_register_composite(dev, name, NULL, 0, NULL, NULL, + NULL, NULL, gate_hw, gate_ops, + fixed_hw, fixed_ops, flags); +} diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index 33e7e64..82dd006 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -343,10 +343,12 @@ struct clk_composite { struct clk_hw *mux_hw; struct clk_hw *div_hw; struct clk_hw *gate_hw; + struct clk_hw *fixed_hw; const struct clk_ops *mux_ops; const struct clk_ops *div_ops; const struct clk_ops *gate_ops; + const struct clk_ops *fixed_ops; }; struct clk *clk_register_composite(struct device *dev, const char *name, @@ -356,6 +358,10 @@ struct clk *clk_register_composite(struct device *dev, const char *name, struct clk_hw *gate_hw, const struct clk_ops *gate_ops, unsigned long flags); +struct clk *clk_register_gatable_osc(struct device *dev, const char *name, + struct clk_hw *fixed_hw, const struct clk_ops *fixed_ops, + struct clk_hw *gate_hw, const struct clk_ops *gate_ops, + unsigned long flags); /** * clk_register - allocate a new clock, register it and return an opaque cookie * @dev: device that is registering this clock