From patchwork Sat Mar 10 07:54:22 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mike Turquette X-Patchwork-Id: 7198 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id 795F123E0E for ; Sat, 10 Mar 2012 07:54:29 +0000 (UTC) Received: from mail-iy0-f180.google.com (mail-iy0-f180.google.com [209.85.210.180]) by fiordland.canonical.com (Postfix) with ESMTP id 28272A180B5 for ; Sat, 10 Mar 2012 07:54:29 +0000 (UTC) Received: by mail-iy0-f180.google.com with SMTP id e36so4511774iag.11 for ; Fri, 09 Mar 2012 23:54:29 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-forwarded-to:x-forwarded-for:delivered-to:received-spf:sender :from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references :x-gm-message-state; bh=8v00lGhYBDottJUkm7VPl4sc6OGSvO9G/v5lyYS/uAQ=; b=n666W4Sy7hWmwzgV7ElEp3IbVxsHVkuBuvLu3rj59MuXf+vMBVX+F7lHs07mrSXaeU Us8Jk4Dx68MjXDSqtRL0IU7Rn+2mn4NtSP2oE7bQZw44KNcImYQ/OfmIwnScbzKI2hXi qYhZHbeNhpLYorEUKmuurZttWdiBgSMo0C3s6mTfLPBxYenGvCnqCUh0I+Wq/ClTbvyI TXtgtlmBx3hFvw/5WO5lxWSywqdEqa1hiauQGk7kvuCwddNpkN/TglgTO4dhXib9znIR GgZkd6HCZPOdbR3XEeL2sRuiFccnyicAHYbIroYn5Ofu2pow2b19nAQMM3vmPSt2CMuL iXXw== Received: by 10.50.158.133 with SMTP id wu5mr7888781igb.50.1331366068915; Fri, 09 Mar 2012 23:54:28 -0800 (PST) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.231.53.18 with SMTP id k18csp3047ibg; Fri, 9 Mar 2012 23:54:28 -0800 (PST) Received: by 10.68.196.226 with SMTP id ip2mr8705566pbc.75.1331366067825; Fri, 09 Mar 2012 23:54:27 -0800 (PST) Received: from na3sys009aog101.obsmtp.com ([74.125.149.67]) by mx.google.com with SMTP id u10si9997742pbv.232.2012.03.09.23.54.27 (version=TLSv1/SSLv3 cipher=OTHER); Fri, 09 Mar 2012 23:54:27 -0800 (PST) Received-SPF: pass (google.com: domain of mturquette@ti.com designates 74.125.149.67 as permitted sender) client-ip=74.125.149.67; Authentication-Results: mx.google.com; spf=pass (google.com: domain of mturquette@ti.com designates 74.125.149.67 as permitted sender) smtp.mail=mturquette@ti.com Received: from mail-iy0-f179.google.com ([209.85.210.179]) (using TLSv1) by na3sys009aob101.postini.com ([74.125.148.12]) with SMTP ID DSNKT1sIsn2Od1DDJlMqm5c7+EWsk1PaIvnr@postini.com; Fri, 09 Mar 2012 23:54:27 PST Received: by iakh37 with SMTP id h37so4309876iak.24 for ; Fri, 09 Mar 2012 23:54:26 -0800 (PST) Received: by 10.50.140.2 with SMTP id rc2mr7835400igb.22.1331366065929; Fri, 09 Mar 2012 23:54:25 -0800 (PST) Received: from singularity.gateway.2wire.net (adsl-69-228-80-100.dsl.pltn13.pacbell.net. [69.228.80.100]) by mx.google.com with ESMTPS id cv10sm4380550igc.13.2012.03.09.23.54.21 (version=TLSv1/SSLv3 cipher=OTHER); Fri, 09 Mar 2012 23:54:24 -0800 (PST) Sender: "Turquette, Mike" From: Mike Turquette To: Russell King Cc: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linaro-dev@lists.linaro.org, patches@linaro.org, Mike Turquette , Mike Turquette , Jeremy Kerr , Thomas Gleixner , Arnd Bergman , Paul Walmsley , Shawn Guo , Sascha Hauer , Richard Zhao , Saravana Kannan , Magnus Damm , Rob Herring , Mark Brown , Linus Walleij , Stephen Boyd , Amit Kucheria , Deepak Saxena , Grant Likely , Andrew Lunn Subject: [PATCH v6 1/3] Documentation: common clk API Date: Fri, 9 Mar 2012 23:54:22 -0800 Message-Id: <1331366064-1273-2-git-send-email-mturquette@linaro.org> X-Mailer: git-send-email 1.7.9.3 In-Reply-To: <1331366064-1273-1-git-send-email-mturquette@linaro.org> References: <1331366064-1273-1-git-send-email-mturquette@linaro.org> X-Gm-Message-State: ALoCoQlVB2f800VnAjrIUgU/TxiGXlTFQB0wP/59zF8PEHZCx3xtQvVpXTCkzlg/BOKmGUKrZ02y Provide documentation for the common clk structures and APIs. This code can be found in drivers/clk/ and include/linux/clk*.h. Signed-off-by: Mike Turquette Signed-off-by: Mike Turquette Cc: Russell King Cc: Jeremy Kerr Cc: Thomas Gleixner Cc: Arnd Bergman Cc: Paul Walmsley Cc: Shawn Guo Cc: Sascha Hauer Cc: Richard Zhao Cc: Saravana Kannan Cc: Magnus Damm Cc: Rob Herring Cc: Mark Brown Cc: Linus Walleij Cc: Stephen Boyd Cc: Amit Kucheria Cc: Deepak Saxena Cc: Grant Likely Cc: Andrew Lunn Reviewed-by: Andrew Lunn --- Changes since v5: * __clk_init must be called for statically initialized clocks * added "clk_ops matrix" to better clarify which ops are mandatory Documentation/clk.txt | 233 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 233 insertions(+), 0 deletions(-) create mode 100644 Documentation/clk.txt diff --git a/Documentation/clk.txt b/Documentation/clk.txt new file mode 100644 index 0000000..1943fae --- /dev/null +++ b/Documentation/clk.txt @@ -0,0 +1,233 @@ + The Common Clk Framework + Mike Turquette + +This document endeavours to explain the common clk framework details, +and how to port a platform over to this framework. It is not yet a +detailed explanation of the clock api in include/linux/clk.h, but +perhaps someday it will include that information. + + Part 1 - introduction and interface split + +The common clk framework is an interface to control the clock nodes +available on various devices today. This may come in the form of clock +gating, rate adjustment, muxing or other operations. This framework is +enabled with the CONFIG_COMMON_CLK option. + +The interface itself is divided into two halves, each shielded from the +details of its counterpart. First is the common definition of struct +clk which unifies the framework-level accounting and infrastructure that +has traditionally been duplicated across a variety of platforms. Second +is a common implementation of the clk.h api, defined in +drivers/clk/clk.c. Finally there is struct clk_ops, whose operations +are invoked by the clk api implementation. + +The second half of the interface is comprised of the hardware-specific +callbacks registered with struct clk_ops and the corresponding +hardware-specific structures needed to model a particular clock. For +the remainder of this document any reference to a callback in struct +clk_ops, such as .enable or .set_rate, implies the hardware-specific +implementation of that code. Likewise, references to struct clk_foo +serve as a convenient shorthand for the implementation of the +hardware-specific bits for the hypothetical "foo" hardware. + +Tying the two halves of this interface together is struct clk_hw, which +is defined in struct clk_foo and pointed to within struct clk. This +allows easy for navigation between the two discrete halves of the common +clock interface. + + Part 2 - common data structures and api + +Below is the common struct clk definition from +include/linux/clk-private.h, modified for brevity: + + struct clk { + const char *name; + const struct clk_ops *ops; + struct clk_hw *hw; + char **parent_names; + struct clk **parents; + struct clk *parent; + struct hlist_head children; + struct hlist_node child_node; + ... + }; + +The members above make up the core of the clk tree topology. The clk +api itself defines several driver-facing functions which operate on +struct clk. That api is documented in include/linux/clk.h. + +Platforms and devices utilizing the common struct clk use the struct +clk_ops pointer in struct clk to perform the hardware-specific parts of +the operations defined in clk.h: + + struct clk_ops { + int (*prepare)(struct clk_hw *hw); + void (*unprepare)(struct clk_hw *hw); + int (*enable)(struct clk_hw *hw); + void (*disable)(struct clk_hw *hw); + int (*is_enabled)(struct clk_hw *hw); + unsigned long (*recalc_rate)(struct clk_hw *hw, + unsigned long parent_rate); + long (*round_rate)(struct clk_hw *hw, unsigned long, + unsigned long *); + int (*set_parent)(struct clk_hw *hw, u8 index); + u8 (*get_parent)(struct clk_hw *hw); + int (*set_rate)(struct clk_hw *hw, unsigned long); + void (*init)(struct clk_hw *hw); + }; + + Part 3 - hardware clk implementations + +The strength of the common struct clk comes from its .ops and .hw pointers +which abstract the details of struct clk from the hardware-specific bits, and +vice versa. To illustrate consider the simple gateable clk implementation in +drivers/clk/clk-gate.c: + +struct clk_gate { + struct clk_hw hw; + void __iomem *reg; + u8 bit_idx; + ... +}; + +struct clk_gate contains struct clk_hw hw as well as hardware-specific +knowledge about which register and bit controls this clk's gating. +Nothing about clock topology or accounting, such as enable_count or +notifier_count, is needed here. That is all handled by the common +framework code and struct clk. + +Let's walk through enabling this clk from driver code: + + struct clk *clk; + clk = clk_get(NULL, "my_gateable_clk"); + + clk_prepare(clk); + clk_enable(clk); + +The call graph for clk_enable is very simple: + +clk_enable(clk); + clk->ops->enable(clk->hw); + [resolves to...] + clk_gate_enable(hw); + [resolves struct clk gate with to_clk_gate(hw)] + clk_gate_set_bit(gate); + +And the definition of clk_gate_set_bit: + +static void clk_gate_set_bit(struct clk_gate *gate) +{ + u32 reg; + + reg = __raw_readl(gate->reg); + reg |= BIT(gate->bit_idx); + writel(reg, gate->reg); +} + +Note that to_clk_gate is defined as: + +#define to_clk_gate(_hw) container_of(_hw, struct clk_gate, clk) + +This pattern of abstraction is used for every clock hardware +representation. + + Part 4 - supporting your own clk hardware + +When implementing support for a new type of clock it only necessary to +include the following header: + +#include + +include/linux/clk.h is included within that header and clk-private.h +must never be included from the code which implements the operations for +a clock. More on that below in Part 5. + +To construct a clk hardware structure for your platform you must define +the following: + +struct clk_foo { + struct clk_hw hw; + ... hardware specific data goes here ... +}; + +To take advantage of your data you'll need to support valid operations +for your clk: + +struct clk_ops clk_foo_ops { + .enable = &clk_foo_enable; + .disable = &clk_foo_disable; +}; + +Implement the above functions using container_of: + +#define to_clk_foo(_hw) container_of(_hw, struct clk_foo, hw) + +int clk_foo_enable(struct clk_hw *hw) +{ + struct clk_foo *foo; + + foo = to_clk_foo(hw); + + ... perform magic on foo ... + + return 0; +}; + +Below is a matrix detailing which clk_ops are mandatory based upon the +hardware capbilities of that clock. A cell marked as "y" means +mandatory, a cell marked as "n" implies that either including that +callback is invalid or otherwise uneccesary. Empty cells are either +optional or must be evaluated on a case-by-case basis. + + clock hardware characteristics + ----------------------------------------------------------- + | gate | change rate | single parent | multiplexer | root | + |------|-------------|---------------|-------------|------| +.prepare | | | | | | +.unprepare | | | | | | + | | | | | | +.enable | y | | | | | +.disable | y | | | | | +.is_enabled | y | | | | | + | | | | | | +.recalc_rate | | y | | | | +.round_rate | | y | | | | +.set_rate | | y | | | | + | | | | | | +.set_parent | | | n | y | n | +.get_parent | | | n | y | n | + | | | | | | +.init | | | | | | + ----------------------------------------------------------- + +Finally, register your clock at run-time with a hardware-specific +registration function. This function simply populates struct clk_foo's +data and then passes the common struct clk parameters to the framework +with a call to: + +clk_register(...) + +See the basic clock types in drivers/clk/clk-*.c for examples. + + Part 5 - static initialization of clock data + +For platforms with many clocks (often numbering into the hundreds) it +may be desirable to statically initialize some clock data. This +presents a problem since the definition of struct clk should be hidden +from everyone except for the clock core in drivers/clk/clk.c. + +To get around this problem struct clk's definition is exposed in +include/linux/clk-private.h along with some macros for more easily +initializing instances of the basic clock types. These clocks must +still be initialized with the common clock framework via a call to +__clk_init. + +clk-private.h must NEVER be included by code which implements struct +clk_ops callbacks, nor must it be included by any logic which pokes +around inside of struct clk at run-time. To do so is a layering +violation. + +To better enforce this policy, always follow this simple rule: any +statically initialized clock data MUST be defined in a separate file +from the logic that implements its ops. Basically separate the logic +from the data and all is well.