もともと、Linux Kernelのソースコードの一部なので、GPLv2扱いになる(はずの認識)。
https://www.kernel.org/doc/html/latest/index.html
Licensing documentation
The following describes the license of the Linux kernel source code (GPLv2), how to properly mark the license of individual files in the source tree, as well as links to the full license text.
https://www.kernel.org/doc/html/latest/process/license-rules.html#kernel-licensing
The Common Clk Framework
Author: Mike Turquette mturquette@ti.com
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.
このドキュメントでは、一般的なclk frameworkの詳細と、このframeworkをプラットフォームを越えて異色する方法を説明しています。include/linux/clk.h
内のclock apiの詳細説明はありませんが、おそらくいくつかは含まれるでしょう。
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.
共通clk frameworkは、今日様々なデバイスで有効なクロックノードを制御するインターフェイスである。これは、clock gating、rate adjustment, muxing(多重化) あるいはほかの操作を実現する。このframworkは、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.
第1は、clk構造体の共通定義である。clk構造体は、従来様々なプラットフォームで複製されてきたframework-level accountingとインフラストラクチャを統合するものである。
Second is a common implementation of the clk.h api, defined in
drivers/clk/clk.c
.
第2は、drivers/clk/clk.c
に定義された、clk.h apiの共通実装である。
Finally there is struct clk_ops, whose operations are invoked by the clk api implementation.
最後に、clk_ops構造体があり、clk api 実装によって呼び出されます。
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.
インターフェイスの後半は、clk_ops構造体に登録されたハードウェア固有のコールバックと、特定のクロックのモデル化に必要な、対応するハードウェア固有の構造で構成されています。
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.
このドキュメントの残りでは、clk_ops構造体に含まれるコールバックのいくつかを参照する。例えば、.enable や .set_rateなど、ハードウェア固有の実装を意味する。
Likewise, references to struct clk_foo serve as a convenient shorthand for the implementation of the hardware-specific bits for the hypothetical "foo" hardware.
同様に、clk_foo構造体は、架空の"foo"ハードウェアに対する、ハードウェア固有の実装に関して、便利な省略形として機能をする。
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_core.
このインターフェイスの、2つの半分を統合するのが、clk_hw構造体でです。これは、clk_foo構造体で定義され、clk_core構造体内でポインタされます。
This allows for easy navigation between the two discrete halves of the common clock interface.
これにより共通クロックインターフェイスの、2つの分かれている半分の間でのナビゲーションがやりやすくなります。
Common data structures and api
Below is the common struct clk_core definition from
drivers/clk/clk.c
, modified for brevity::
下記は、drivers/clk/clk.c
で定義されている、共通clk_core構造体である。簡潔化するために修正されている。
struct clk_core {
const char *name;
const struct clk_ops *ops;
struct clk_hw *hw;
struct module *owner;
struct clk_core *parent;
const char **parent_names;
struct clk_core **parents;
u8 num_parents;
u8 new_parent_index;
...
};
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
.
上記のメンバーは、clk tree topologyのコアを構成します。clk api自体は、clk構造体に対して制御を行うためのdriver界面のいくつかの関数を定義しています。このapiは、include/linux/clk.h
にてドキュメント化されています。
Platforms and devices utilizing the common struct clk_core use the struct clk_ops pointer in struct clk_core to perform the hardware-specific parts of the operations defined in clk-provider.h::
共通clk_core構造体を利用するプラットフォームとデバイスドライバは、clk_core構造体内のclk_ops構造体へのポインタを用いて、clk-providor.hで定義された、ハードウェア固有の処理を実行します。
struct clk_ops {
int (*prepare)(struct clk_hw *hw);
void (*unprepare)(struct clk_hw *hw);
int (*is_prepared)(struct clk_hw *hw);
void (*unprepare_unused)(struct clk_hw *hw);
int (*enable)(struct clk_hw *hw);
void (*disable)(struct clk_hw *hw);
int (*is_enabled)(struct clk_hw *hw);
void (*disable_unused)(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 rate,
unsigned long *parent_rate);
int (*determine_rate)(struct clk_hw *hw,
struct clk_rate_request *req);
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 rate,
unsigned long parent_rate);
int (*set_rate_and_parent)(struct clk_hw *hw,
unsigned long rate,
unsigned long parent_rate,
u8 index);
unsigned long (*recalc_accuracy)(struct clk_hw *hw,
unsigned long parent_accuracy);
int (*get_phase)(struct clk_hw *hw);
int (*set_phase)(struct clk_hw *hw, int degrees);
void (*init)(struct clk_hw *hw);
void (*debug_init)(struct clk_hw *hw,
struct dentry *dentry);
};
Hardware clk implementations
The strength of the common struct clk_core comes from its .ops and .hw pointers which abstract the details of struct clk from the hardware-specific bits, and vice versa.
共通clk_core構造体の強みは、それ自体が.opsと.hw pointerによって、ハードウェア固有のbitに対する抽象化ができていることである。逆も同様です。
To illustrate consider the simple gateable clk implementation in
drivers/clk/clk-gate.c
::
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.
clk_gate構造体は、当該clockのgatingを制御するためのレジスタとbitに関するハードウェア固有の知識として、clk_hw構造体を含みます。
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_core.
ここで、enable_countあるいはnotifier_count等のような、clock topologyやaccountingについては必要ありません。これはすべて共通のフレームワークコードとclk_core構造体によって処理されます。
Let's walk through enabling this clk from driver code::
ドライバコードから、このclk構造体を有効化する手順を確認しましょう。
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_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::
そして、clk_get_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::
ここで、to_clk_gateは以下のように定義されます。
#define to_clk_gate(_hw) container_of(_hw, struct clk_gate, hw)
This pattern of abstraction is used for every clock hardware representation.
この抽象化のパターンは、全てのclock hard ware表現で利用されます。
Supporting your own clk hardware
When implementing support for a new type of clock it is only necessary to include the following header::
新しいclock typeをサポートする実装をする時、下記のヘッダをincludeするだけでよい。
#include <linux/clk-provider.h>
To construct a clk hardware structure for your platform you must define the following::
あなたのプラットフォームのclk hardware structureを構成するには、下記の定義が必要になります。
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::
データを利用するメリットを活かすには、clkを正しい制御手段のサポートが必要です。
struct clk_ops clk_foo_ops = {
.enable = &clk_foo_enable,
.disable = &clk_foo_disable,
};
Implement the above functions using container_of::
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 capabilities of that clock.
下記は、そのクロックにおいてハードウェア機能に基づいてclk_opsが必要となるかの詳細を示したマトリックスである。
A cell marked as "y" means mandatory, a cell marked as "n" implies that either including that callback is invalid or otherwise unnecessary.
"y"とマークされたセルが必須であり、"n"は当該コールバックが無効であるか必要ないかを意味している。
Empty cells are either optional or must be evaluated on a case-by-case basis.
空のセルは、オプションであるか、ケースバイベースによって評価する必要があります。
.. table:: 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 [1]_ | | | |
+----------------+------+-------------+---------------+-------------+------+
|.determine_rate | | y [1]_ | | | |
+----------------+------+-------------+---------------+-------------+------+
|.set_rate | | y | | | |
+----------------+------+-------------+---------------+-------------+------+
+----------------+------+-------------+---------------+-------------+------+
|.set_parent | | | n | y | n |
+----------------+------+-------------+---------------+-------------+------+
|.get_parent | | | n | y | n |
+----------------+------+-------------+---------------+-------------+------+
+----------------+------+-------------+---------------+-------------+------+
|.recalc_accuracy| | | | | |
+----------------+------+-------------+---------------+-------------+------+
+----------------+------+-------------+---------------+-------------+------+
|.init | | | | | |
+----------------+------+-------------+---------------+-------------+------+
[1] either one of round_rate or determine_rate is required.
[1] round_rate もしくは determine_rate のいずれかで必要となる
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_foo構造体のデータを入力し、次の呼び出しで一般的なclk構造体パラメータをframworkに伝えます。
clk_register(...)
See the basic clock types in
drivers/clk/clk-*.c
for examples.
drivers/clk/clk-*.c
内の基本的なclock typeを参考としてみてください。
Disabling clock gating of unused clocks
Sometimes during development it can be useful to be able to bypass the default disabling of unused clocks.
開発中においてはしばしば、デフォルトでクロックを無効化することで有効であることがある。
For example, if drivers aren't enabling clocks properly but rely on them being on from the bootloader, bypassing the disabling means that the driver will remain functional while the issues are sorted out.
例えば、ドライバーがクロックを適切に有効にしていないが、ブートローダーからの恩に依存している場合、無効化をbypassすることで問題が解決されるばでドライバーが機能し続ける。
To bypass this disabling, include "clk_ignore_unused" in the bootargs to the kernel.
この無効化をbypassするには、kernelのbootargsに"clk_ignore_unused"を含めてください。
Locking
The common clock framework uses two global locks, the prepare lock and the enable lock.
共通clock frameworkは2つのグローバルロックを利用しています。prepare lockと、enable lockです。
The enable lock is a spinlock and is held across calls to the .enable, .disable operations.
enable lockはspinlockであり、 .enableや.disable 処理を実行する間に保持されます。
Those operations are thus not allowed to sleep, and calls to the clk_enable(), clk_disable() API functions are allowed in atomic context.
したがってこれらの処理はsleepできず、clk_enable()とcld_disable() APIはatomic context内で呼び出すことが許容されます。
.
For clk_is_enabled() API, it is also designed to be allowed to be used in atomic context.
また、clk_is_enable() APIは、atomic context内で利用されることを許容された設計になっています。
However, it doesn't really make any sense to hold the enable lock in core, unless you want to do something else with the information of the enable state with that lock held.
しかし、コアがenable lockをholdしているときに、lock holdでの有効状態の情報を用いて別のことをしたい場合を除きます。
Otherwise, seeing if a clk is enabled is a one-shot read of the enabled state, which could just as easily change after the function returns because the lock is released.
それ以外の場合、クロックがenableであるかを確認する事は、enabled stateをワンショットで読み出す事であり、ロックが解放されるので、関数が戻った後にも簡単に変更できます。
Thus the user of this API needs to handle synchronizing the read of the state with whatever they're using it for to make sure that the enable state doesn't change during that time.
したがって、このAPIのユーザーは、除隊の読み取りを、それが使用しているものと同期して、enable stateがその間に変更されないようにする必要があります。
.
The prepare lock is a mutex and is held across calls to all other operations.
prepare lockはmutexであり、その他の処理を呼び出している間で保持されます。
All those operations are allowed to sleep, and calls to the corresponding API functions are not allowed in atomic context.
これらの操作はすべてスリープすることができ、対応するAPI関数の呼び出しは、atomic contextでは許容されていません。
This effectively divides operations in two groups from a locking perspective.
これにより、ロックの観点からすると、処理が2つのグループに効果的に分割されます。
.
Drivers don't need to manually protect resources shared between the operations of one group, regardless of whether those resources are shared by multiple clocks or not.
ドライバーは、リソースが複数のクロックで共有されているかどうかにかかわらず、1つのグループの捜査官で共有しているリソースを手動で保護する必要はありません。
However, access to resources that are shared between operations of the two groups needs to be protected by the drivers.
ただし、2つのグループの操作間で共有されるリソースへのアクセスは、ドライバーによって保護する必要があります。
An example of such a resource would be a register that controls both the clock rate and the clock enable/disable state.
このようなリソースの一例として、クロックレートとクロックの有効/無効状態の両方を制御するレジスタがあります。
.
The clock framework is reentrant, in that a driver is allowed to call clock framework functions from within its implementation of clock operations.
clock frameworkは、ドライバーがクロック操作の実装内から呼び出すことができるという点でリエントラントです。
This can for instance cause a .set_rate operation of one clock being called from within the .set_rate operation of another clock.
これにより、例えば、あるクロックの.set_rate操作が、別のクロックの.set_rate操作内から呼び出される可能性があります。
This case must be considered in the driver implementations, but the code flow is usually controlled by the driver in that case.
このケースは、ドライバーの実装で考慮する必要があります。しかし、コードフローは通常そのような場合、ドライバーによって制御されます。
.
Note that locking must also be considered when code outside of the common clock framework needs to access resources used by the clock operations.
共通clock frameworkの外部コードが、クロック操作で使用するリソースにアクセスする必要がる場合、ロックも考慮する必要がある事に注意してください。
This is considered out of scope of this document.
それは本ドキュメントのスコープ外になります。