[커널 18차] 64주차
2022.08.13 22:22
clk 진행 완료
git : https://github.com/iamroot18/5.10/commit/784e5b69d2f9c701cb84529eda9b3cec3db0c14f
diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
index a254512965eb..e7818cc63afa 100644
--- a/drivers/clk/bcm/clk-bcm2835.c
+++ b/drivers/clk/bcm/clk-bcm2835.c
@@ -2306,6 +2306,37 @@ static const struct cprman_plat_data cprman_bcm2711_plat_data = {
.soc = SOC_BCM2711,
};
+/*
+ * IAMROOT, 2022.08.13:
+ * clocks {
+ * clk_osc: clk-osc {
+ * compatible = "fixed-clock";
+ * #clock-cells = <0>;
+ * clock-output-names = "osc";
+ * clock-frequency = <19200000>;
+ * };
+ * };
+ *
+ * clocks: cprman@7e101000 {
+ * compatible = "brcm,bcm2835-cprman";
+ * #clock-cells = <1>;
+ * reg = <0x7e101000 0x2000>;
+ * clocks = <&clk_osc>,
+ * <&dsi0 0>, <&dsi0 1>, <&dsi0 2>,
+ * <&dsi1 0>, <&dsi1 1>, <&dsi1 2>;
+ * };
+ *
+ * uart0: serial@7e201000 {
+ * compatible = "arm,pl011", "arm,primecell";
+ * reg = <0x7e201000 0x200>;
+ * clocks = <&clocks BCM2835_CLOCK_UART>, #BCM2835_CLOCK_UART 19
+ * <&clocks BCM2835_CLOCK_VPU>; #BCM2835_CLOCK_VPU 20
+ * clock-names = "uartclk", "apb_pclk";
+ * };
+ *
+ * BCM2835_CLOCK_UART 19 : cprman의 19번째 clock이라는 뜻. "uartclk"이름을 가진다.
+ * BCM2835_CLOCK_VPU 20 : cprman의 20번째 clock이라는 뜻. "apb_pclk"이름을 가진다.
+ */
static const struct of_device_id bcm2835_clk_of_match[] = {
{ .compatible = "brcm,bcm2835-cprman", .data = &cprman_bcm2835_plat_data },
{ .compatible = "brcm,bcm2711-cprman", .data = &cprman_bcm2711_plat_data },
diff --git a/drivers/clk/clk-conf.c b/drivers/clk/clk-conf.c
index 13b0121de1b5..447cbf94d450 100644
--- a/drivers/clk/clk-conf.c
+++ b/drivers/clk/clk-conf.c
@@ -25,6 +25,17 @@
* status = "okay";
* ..
* }
+ *
+ * ----
+ * - assigned-clocks
+ * ex) assigned-clocks = <&clkcon 0>, <&pll 2>;
+ * clkcon 0번, pll2번에 대해 clock 변경 요청
+ * - assigned-clock-parents
+ * ex) assigned-clock-parents = <&pll 2>;
+ * ^clkcon 0의 parent는 pll 2라고 정해버리는것.
+ * - assigned-clock-rates
+ * ex) assigned-clock-rates = <0>, <460800>
+ * clkocn 0는 안한다는것^ ^pll 2는 460800으로 쓰겟다는것.
*/
static int __set_clk_parents(struct device_node *node, bool clk_supplier)
{
@@ -176,6 +187,9 @@ static int __set_clk_rates(struct device_node *node, bool clk_supplier)
* 'assigned-clock-parents' 속성에 나열된 clok의 clock 공급자일 수도 있는 경우
* @clk_supplier 인수는 true로 설정되어야 합니다. @clk_supplier가 false이면 함수는
* @node가 시계 공급자이기도 하다고 결정하자마자 0을 반환하며 종료됩니다.
+ *
+ * - dts의 assigned-clocks관련 정보를 참조해 parent와 rate를 미리 설정 해야되는지를
+ * 확인해 설정한다.
*/
int of_clk_set_defaults(struct device_node *node, bool clk_supplier)
{
diff --git a/drivers/clk/clk-fixed-factor.c b/drivers/clk/clk-fixed-factor.c
index 4e4b6d367612..3403dcd58bf6 100644
--- a/drivers/clk/clk-fixed-factor.c
+++ b/drivers/clk/clk-fixed-factor.c
@@ -57,6 +57,13 @@ static int clk_factor_set_rate(struct clk_hw *hw, unsigned long rate,
return 0;
}
+/*
+ * IAMROOT, 2022.08.13:
+ * - __clk_core_init()참고.
+ * - set_rate가 지정되면 round_rate, determine_rate 둘중하나와
+ * recalc_rate가 존재해야된다.
+ * 설정을 못하는 clk이 왔을때 대처방안을 마련해줘야되는 개념.
+ */
const struct clk_ops clk_fixed_factor_ops = {
.round_rate = clk_factor_round_rate,
.set_rate = clk_factor_set_rate,
@@ -76,6 +83,11 @@ static void devm_clk_hw_register_fixed_factor_release(struct device *dev, void *
clk_hw_unregister(&fix->hw);
}
+/*
+ * IAMROOT, 2022.08.13:
+ * - @devm driver에서 exit시 자동해제를 위할때 true설정.
+ * - fixed factor를 등록한다. mult, div등을 설정하고 등록한다.
+ */
static struct clk_hw *
__clk_hw_register_fixed_factor(struct device *dev, struct device_node *np,
const char *name, const char *parent_name, int index,
@@ -83,15 +95,28 @@ __clk_hw_register_fixed_factor(struct device *dev, struct device_node *np,
bool devm)
{
struct clk_fixed_factor *fix;
+/*
+ * IAMROOT, 2022.08.13:
+ * - hw의 init을 잠깐 전달해준다.
+ */
struct clk_init_data init = { };
struct clk_parent_data pdata = { .index = index };
struct clk_hw *hw;
int ret;
+/*
+ * IAMROOT, 2022.08.13:
+ * - 자동해제요청(@devm)이 있으면 @dev가 무조건 필요하다.
+ */
/* You can't use devm without a dev */
if (devm && !dev)
return ERR_PTR(-EINVAL);
+/*
+ * IAMROOT, 2022.08.13:
+ * - driver 요청이라고 하면 자동해제가능한 alloc을 쓴다.
+ * 자동해제할때 devm_clk_hw_register_fixed_factor_release를 파괴자로 사용하나다.
+ */
if (devm)
fix = devres_alloc(devm_clk_hw_register_fixed_factor_release,
sizeof(*fix), GFP_KERNEL);
@@ -112,6 +137,11 @@ __clk_hw_register_fixed_factor(struct device *dev, struct device_node *np,
init.parent_names = &parent_name;
else
init.parent_data = &pdata;
+
+/*
+ * IAMROOT, 2022.08.13:
+ * - fixed factor는 무조건 clk을 공급받을 한개의 부모가 존재한다.
+ */
init.num_parents = 1;
hw = &fix->hw;
@@ -193,6 +223,10 @@ static const struct of_device_id set_rate_parent_matches[] = {
{ /* Sentinel */ },
};
+/*
+ * IAMROOT, 2022.08.13:
+ * - dts에서 div, mult, clk_name, CLK_SET_RATE_PARENT여부등을 확인후.
+ */
static struct clk_hw *_of_fixed_factor_clk_setup(struct device_node *node)
{
struct clk_hw *hw;
@@ -242,6 +276,10 @@ static struct clk_hw *_of_fixed_factor_clk_setup(struct device_node *node)
* of_fixed_factor_clk_setup() - Setup function for simple fixed factor clock
* @node: device node for the clock
*/
+/*
+ * IAMROOT, 2022.08.13:
+ * - fixed factor clk을 setup 한다.
+ */
void __init of_fixed_factor_clk_setup(struct device_node *node)
{
_of_fixed_factor_clk_setup(node);
diff --git a/drivers/clk/clk-fixed-rate.c b/drivers/clk/clk-fixed-rate.c
index 41a41945763b..bec540d9be28 100644
--- a/drivers/clk/clk-fixed-rate.c
+++ b/drivers/clk/clk-fixed-rate.c
@@ -49,6 +49,15 @@ const struct clk_ops clk_fixed_rate_ops = {
};
EXPORT_SYMBOL_GPL(clk_fixed_rate_ops);
+/*
+ * IAMROOT, 2022.08.13:
+ * - fixed rate를 등록한다.
+ * parent관련 3개의 인자중 하나를 다음과 같은 함수로 통해서 정해서 사용한다.
+ * clk_hw_register_fixed_rate : parent_name
+ * clk_hw_register_fixed_rate_parent_hw : parent_hw
+ * clk_hw_register_fixed_rate_parent_data : parent_data
+ *
+ */
struct clk_hw *__clk_hw_register_fixed_rate(struct device *dev,
struct device_node *np, const char *name,
const char *parent_name, const struct clk_hw *parent_hw,
@@ -72,6 +81,13 @@ struct clk_hw *__clk_hw_register_fixed_rate(struct device *dev,
init.parent_names = parent_name ? &parent_name : NULL;
init.parent_hws = parent_hw ? &parent_hw : NULL;
init.parent_data = parent_data;
+
+/*
+ * IAMROOT, 2022.08.13:
+ * - fixed factor끼리도 parent관계가 될수있다.
+ * ex) gemini clock
+ * xtal(30MHz) -> tvc(27MHz)
+ */
if (parent_name || parent_hw || parent_data)
init.num_parents = 1;
else
@@ -85,6 +101,11 @@ struct clk_hw *__clk_hw_register_fixed_rate(struct device *dev,
/* register the clock */
hw = &fixed->hw;
+
+/*
+ * IAMROOT, 2022.08.13:
+ * - device tree로 왔으면 of_clk_hw_register. 아니면 clk_hw_register.
+ */
if (dev || !np)
ret = clk_hw_register(dev, hw);
else if (np)
@@ -157,6 +178,10 @@ static struct clk_hw *_of_fixed_clk_setup(struct device_node *node)
of_property_read_string(node, "clock-output-names", &clk_name);
+/*
+ * IAMROOT, 2022.08.13:
+ * - name, fixed_rate, fixed_accuracy
+ */
hw = clk_hw_register_fixed_rate_with_accuracy(NULL, clk_name, NULL,
0, rate, accuracy);
if (IS_ERR(hw))
@@ -175,6 +200,10 @@ static struct clk_hw *_of_fixed_clk_setup(struct device_node *node)
* of_fixed_clk_setup() - Setup function for simple fixed rate clock
* @node: device node for the clock
*/
+/*
+ * IAMROOT, 2022.08.13:
+ * - fixed rate등록.
+ */
void __init of_fixed_clk_setup(struct device_node *node)
{
_of_fixed_clk_setup(node);
diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c
index 20582aae7a35..b74845068236 100644
--- a/drivers/clk/clk-mux.c
+++ b/drivers/clk/clk-mux.c
@@ -67,6 +67,10 @@ int clk_mux_val_to_index(struct clk_hw *hw, u32 *table, unsigned int flags,
}
EXPORT_SYMBOL_GPL(clk_mux_val_to_index);
+/*
+ * IAMROOT, 2022.08.13:
+ * - @index에 해당하는 table에서 val을 가져와 flag에 따라 가공해서 return한다.
+ */
unsigned int clk_mux_index_to_val(u32 *table, unsigned int flags, u8 index)
{
unsigned int val = index;
@@ -96,6 +100,11 @@ static u8 clk_mux_get_parent(struct clk_hw *hw)
return clk_mux_val_to_index(hw, mux->table, mux->flags, val);
}
+/*
+ * IAMROOT, 2022.08.13:
+ * - table에서 index에서 해당하는 parent를 선택하고, 거기에 저장된 val값을
+ * flag에 따라 수정수 가져온다.
+ */
static int clk_mux_set_parent(struct clk_hw *hw, u8 index)
{
struct clk_mux *mux = to_clk_mux(hw);
@@ -146,6 +155,10 @@ const struct clk_ops clk_mux_ro_ops = {
};
EXPORT_SYMBOL_GPL(clk_mux_ro_ops);
+/*
+ * IAMROOT, 2022.08.13:
+ * - clk_hw_register_fixed_rate류 와 비슷한 방식을 사용해서 등록한다.
+ */
struct clk_hw *__clk_hw_register_mux(struct device *dev, struct device_node *np,
const char *name, u8 num_parents,
const char * const *parent_names,
@@ -241,6 +254,10 @@ struct clk_hw *__devm_clk_hw_register_mux(struct device *dev, struct device_node
}
EXPORT_SYMBOL_GPL(__devm_clk_hw_register_mux);
+/*
+ * IAMROOT, 2022.08.13:
+ * - 등록.
+ */
struct clk *clk_register_mux_table(struct device *dev, const char *name,
const char * const *parent_names, u8 num_parents,
unsigned long flags, void __iomem *reg, u8 shift, u32 mask,
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index 985ff1101bd7..6d480a221010 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -66,6 +66,10 @@ struct clk_core {
u8 new_parent_index;
unsigned long rate;
unsigned long req_rate;
+/*
+ * IAMROOT, 2022.08.13:
+ * - pre로 clock을 계산해볼때 결과값을 저장하는 멤버.
+ */
unsigned long new_rate;
struct clk_core *new_parent;
struct clk_core *new_child;
@@ -106,6 +110,10 @@ struct clk {
};
/*** runtime pm ***/
+/*
+ * IAMROOT, 2022.08.13:
+ * - 절전 상태에 있으면 normal 상태로 전환.
+ */
static int clk_pm_runtime_get(struct clk_core *core)
{
int ret;
@@ -156,6 +164,10 @@ static void clk_prepare_unlock(void)
mutex_unlock(&prepare_lock);
}
+/*
+ * IAMROOT, 2022.08.13:
+ * - 전역 lock enable
+ */
static unsigned long clk_enable_lock(void)
__acquires(enable_lock)
{
@@ -198,6 +210,10 @@ static void clk_enable_unlock(unsigned long flags)
spin_unlock_irqrestore(&enable_lock, flags);
}
+/*
+ * IAMROOT, 2022.08.13:
+ * - 누군가 protected해논지 확인.
+ */
static bool clk_core_rate_is_protected(struct clk_core *core)
{
return core->protect_count;
@@ -474,6 +490,10 @@ unsigned int __clk_get_enable_count(struct clk *clk)
return !clk ? 0 : clk->core->enable_count;
}
+/*
+ * IAMROOT, 2022.08.13:
+ * - @core의 rate를 가져온다.
+ */
static unsigned long clk_core_get_rate_nolock(struct clk_core *core)
{
if (!core)
@@ -487,6 +507,10 @@ static unsigned long clk_core_get_rate_nolock(struct clk_core *core)
* known yet. Best to return 0 as the rate of this clk until we can
* properly recalc the rate based on the parent's rate.
*/
+/*
+ * IAMROOT, 2022.08.13:
+ * - @core parent가 있지만 아지만 parent가 설정이 안된 경우 0으로 그냥 return한다는것.
+ */
return 0;
}
@@ -537,6 +561,12 @@ bool __clk_is_enabled(struct clk *clk)
}
EXPORT_SYMBOL_GPL(__clk_is_enabled);
+/*
+ * IAMROOT, 2022.08.13:
+ * - closest일 경우 절대값으로 차이가 적은 것을,(요구 rate보다 높아도 무관)
+ * 아니면 best < now <= rate(요구 rate보다 높으면 안됨)
+ * 결국 요구 rate보다 높아도되는지 안되는지에대한 차이.
+ */
static bool mux_is_better_rate(unsigned long rate, unsigned long now,
unsigned long best, unsigned long flags)
{
@@ -546,6 +576,10 @@ static bool mux_is_better_rate(unsigned long rate, unsigned long now,
return now <= rate && now > best;
}
+/*
+ * IAMROOT, 2022.08.13:
+ * - parent를 순회해 best rate를 구해온다.
+ */
int clk_mux_determine_rate_flags(struct clk_hw *hw,
struct clk_rate_request *req,
unsigned long flags)
@@ -556,8 +590,20 @@ int clk_mux_determine_rate_flags(struct clk_hw *hw,
struct clk_rate_request parent_req = *req;
/* if NO_REPARENT flag set, pass through to current parent */
+/*
+ * IAMROOT, 2022.08.13:
+ * - 현재 clk에 parent(입력소스) 변경 불가인 경우.
+ * parent rate 변경이 가능 -> parent rate 변경 시도.
+ * parent 가 있음 -> parent rate 가져옴.
+ * parent 가 없음 -> 자신의 rate 가져옴.
+ * 즉 parent rate변경이 불가능한 거면 parent나 자신것을 그대로 쓴다는 의미.
+ */
if (core->flags & CLK_SET_RATE_NO_REPARENT) {
parent = core->parent;
+/*
+ * IAMROOT, 2022.08.13:
+ * - 자신의 clk source 변경은 없고, 최적의 parent의 rate를 선택하게 한다.
+ */
if (core->flags & CLK_SET_RATE_PARENT) {
ret = __clk_determine_rate(parent ? parent->hw : NULL,
&parent_req);
@@ -565,6 +611,10 @@ int clk_mux_determine_rate_flags(struct clk_hw *hw,
return ret;
best = parent_req.rate;
+/*
+ * IAMROOT, 2022.08.13:
+ * - parent를 못바꾸면 parent clk을 가져오고, parent가 없으면 그냥 자기것을 가져온다.
+ */
} else if (parent) {
best = clk_core_get_rate_nolock(parent);
} else {
@@ -581,6 +631,11 @@ int clk_mux_determine_rate_flags(struct clk_hw *hw,
if (!parent)
continue;
+/*
+ * IAMROOT, 2022.08.13:
+ * - 부모한테 영향을 줘야되는 경우. parent clk에서 재귀탐색을 하고,
+ * 아니면 parent의 rate를 바로 가져온다.
+ */
if (core->flags & CLK_SET_RATE_PARENT) {
parent_req = *req;
ret = __clk_determine_rate(parent->hw, &parent_req);
@@ -617,6 +672,11 @@ struct clk *__clk_lookup(const char *name)
return !core ? NULL : core->hw->clk;
}
+/*
+ * IAMROOT, 2022.08.13:
+ * - clks_node(사용자들)에서 사용하는 값들과 clamp하며
+ * - 가장큰 min과 가장 작은 max를 구한다.(교집합)
+ */
static void clk_core_get_boundaries(struct clk_core *core,
unsigned long *min_rate,
unsigned long *max_rate)
@@ -654,6 +714,10 @@ EXPORT_SYMBOL_GPL(clk_hw_set_rate_range);
*
* Returns: 0 on success, -EERROR value on error
*/
+/*
+ * IAMROOT, 2022.08.13:
+ * - @req에 최적인 rate를 구해온다.
+ */
int __clk_mux_determine_rate(struct clk_hw *hw,
struct clk_rate_request *req)
{
@@ -865,6 +929,11 @@ void clk_unprepare(struct clk *clk)
}
EXPORT_SYMBOL_GPL(clk_unprepare);
+/*
+ * IAMROOT, 2022.08.13:
+ * - 재귀적으로 parent까지 올라가며 prepare안되있으면 prepare 시킨다.
+ * 실제 하드웨어적으로 clock을 on해주는 함수.
+ */
static int clk_core_prepare(struct clk_core *core)
{
int ret = 0;
@@ -914,6 +983,10 @@ static int clk_core_prepare(struct clk_core *core)
return ret;
}
+/*
+ * IAMROOT, 2022.08.13:
+ * - clk prepare. (clk on)
+ */
static int clk_core_prepare_lock(struct clk_core *core)
{
int ret;
@@ -1003,6 +1076,11 @@ void clk_disable(struct clk *clk)
}
EXPORT_SYMBOL_GPL(clk_disable);
+/*
+ * IAMROOT, 2022.08.13:
+ * - gate clk enable. enable count가 안되있으면 parent까지 타고 올라가며
+ * enable 및 enable count증가 시킨다.
+ */
static int clk_core_enable(struct clk_core *core)
{
int ret = 0;
@@ -1017,6 +1095,10 @@ static int clk_core_enable(struct clk_core *core)
return -ESHUTDOWN;
if (core->enable_count == 0) {
+/*
+ * IAMROOT, 2022.08.13:
+ * - parent까지 올라가 enable안되있다면 시킨다.
+ */
ret = clk_core_enable(core->parent);
if (ret)
@@ -1039,6 +1121,10 @@ static int clk_core_enable(struct clk_core *core)
return 0;
}
+/*
+ * IAMROOT, 2022.08.13:
+ * - gate clk enable.
+ */
static int clk_core_enable_lock(struct clk_core *core)
{
unsigned long flags;
@@ -1189,6 +1275,10 @@ bool clk_is_enabled_when_prepared(struct clk *clk)
}
EXPORT_SYMBOL_GPL(clk_is_enabled_when_prepared);
+/*
+ * IAMROOT, 2022.08.13:
+ * - clk on 및 gate on
+ */
static int clk_core_prepare_enable(struct clk_core *core)
{
int ret;
@@ -1323,6 +1413,10 @@ static int __init clk_disable_unused(void)
}
late_initcall_sync(clk_disable_unused);
+/*
+ * IAMROOT, 2022.08.13:
+ * - determin or round
+ */
static int clk_core_determine_round_nolock(struct clk_core *core,
struct clk_rate_request *req)
{
@@ -1339,6 +1433,11 @@ static int clk_core_determine_round_nolock(struct clk_core *core,
* - if the calling consumer is the only one which has exclusivity
* over the provider
*/
+/*
+ * IAMROOT, 2022.08.13:
+ * - protected면 core, > determine_rate > round_rate를 우선순위로 설정한다.
+ * ex) __clk_mux_determine_rate,
+ */
if (clk_core_rate_is_protected(core)) {
req->rate = core->rate;
} else if (core->ops->determine_rate) {
@@ -1357,6 +1456,10 @@ static int clk_core_determine_round_nolock(struct clk_core *core,
return 0;
}
+/*
+ * IAMROOT, 2022.08.13:
+ * - @parent의 hw, rate를 그대로 가져온다.
+ */
static void clk_core_init_rate_req(struct clk_core * const core,
struct clk_rate_request *req)
{
@@ -1375,11 +1478,19 @@ static void clk_core_init_rate_req(struct clk_core * const core,
}
}
+/*
+ * IAMROOT, 2022.08.13:
+ * - ops 함수 제공 확인.
+ */
static bool clk_core_can_round(struct clk_core * const core)
{
return core->ops->determine_rate || core->ops->round_rate;
}
+/*
+ * IAMROOT, 2022.08.13:
+ * - @req에 맞는 rate를 구해온다.
+ */
static int clk_core_round_rate_nolock(struct clk_core *core,
struct clk_rate_request *req)
{
@@ -1392,6 +1503,12 @@ static int clk_core_round_rate_nolock(struct clk_core *core,
clk_core_init_rate_req(core, req);
+/*
+ * IAMROOT, 2022.08.13:
+ * - @core에서 detertmin이나 round를 할수없는경우, parent 변경 가능한 경우
+ * parent에서 round를 시도한다.
+ * 그것도 안되면 자기것을 그냥 가져온다.
+ */
if (clk_core_can_round(core))
return clk_core_determine_round_nolock(core, req);
else if (core->flags & CLK_SET_RATE_PARENT)
@@ -1408,8 +1525,16 @@ static int clk_core_round_rate_nolock(struct clk_core *core,
*
* Useful for clk_ops such as .set_rate and .determine_rate.
*/
+/*
+ * IAMROOT, 2022.08.13:
+ * -
+ */
int __clk_determine_rate(struct clk_hw *hw, struct clk_rate_request *req)
{
+/*
+ * IAMROOT, 2022.08.13:
+ * - 재귀호출로 사용할수도있다. 최상위까지 왓을 경우에 대한 탈출조건.
+ */
if (!hw) {
req->rate = 0;
return 0;
@@ -1459,6 +1584,11 @@ EXPORT_SYMBOL_GPL(clk_hw_round_rate);
* use which is then returned. If clk doesn't support round_rate operation
* then the parent rate is returned.
*/
+
+/*
+ * IAMROOT, 2022.08.13:
+ * - @rate에 근접한 실제 사용가능할수있는 clk rate를 구해온다.
+ */
long clk_round_rate(struct clk *clk, unsigned long rate)
{
struct clk_rate_request req;
@@ -1472,9 +1602,17 @@ long clk_round_rate(struct clk *clk, unsigned long rate)
if (clk->exclusive_count)
clk_core_rate_unprotect(clk->core);
+/*
+ * IAMROOT, 2022.08.13:
+ * - clk을 사용하는 모든 사용자들의 범위 이내로 min, max를 clamp 시킨다.
+ */
clk_core_get_boundaries(clk->core, &req.min_rate, &req.max_rate);
req.rate = rate;
+/*
+ * IAMROOT, 2022.08.13:
+ * - rate를 설정할수있는지 확인한다.
+ */
ret = clk_core_round_rate_nolock(clk->core, &req);
if (clk->exclusive_count)
@@ -1503,6 +1641,11 @@ EXPORT_SYMBOL_GPL(clk_round_rate);
* called if all went well, or NOTIFY_STOP or NOTIFY_BAD immediately if
* a driver returns that.
*/
+/*
+ * IAMROOT, 2022.08.13:
+ * - notifier에 등록된 clk이 가리키는 core에만 notify한다.
+ * 참고) dw8250_clk_notifier_cb, gcc_ipq4019_cpu_clk_notifier_fn
+ */
static int __clk_notify(struct clk_core *core, unsigned long msg,
unsigned long old_rate, unsigned long new_rate)
{
@@ -1587,6 +1730,10 @@ long clk_get_accuracy(struct clk *clk)
}
EXPORT_SYMBOL_GPL(clk_get_accuracy);
+/*
+ * IAMROOT, 2022.08.13:
+ * - parent로 일단 rate로 해놓고, ops가 등록되있으면 ops로 rate를 재산출한다.
+ */
static unsigned long clk_recalc(struct clk_core *core,
unsigned long parent_rate)
{
@@ -1751,6 +1898,12 @@ static void clk_core_update_orphan_status(struct clk_core *core, bool is_orphan)
clk_core_update_orphan_status(child, is_orphan);
}
+/*
+ * IAMROOT, 2022.08.13:
+ * - @new_parent가 있으면 core를 new_parent orphan상태로 일치시키고 new_parent의
+ * child로 변경한다.
+ * - @new_parent가 없으면 parent가 없어진 것이므로 orphan으로 변경한다.
+ */
static void clk_reparent(struct clk_core *core, struct clk_core *new_parent)
{
bool was_orphan = core->orphan;
@@ -1758,6 +1911,10 @@ static void clk_reparent(struct clk_core *core, struct clk_core *new_parent)
hlist_del(&core->child_node);
if (new_parent) {
+/*
+ * IAMROOT, 2022.08.13:
+ * - 둘중하나가 orphan 상태가 다르면 core의 orphan상태를 new_parent의 상태로 업데이트
+ */
bool becomes_orphan = new_parent->orphan;
/* avoid duplicate POST_RATE_CHANGE notifications */
@@ -1777,6 +1934,11 @@ static void clk_reparent(struct clk_core *core, struct clk_core *new_parent)
core->parent = new_parent;
}
+/*
+ * IAMROOT, 2022.08.13:
+ * @return old_parent
+ * - @core의 parent를 @parent로 변경한다.
+ */
static struct clk_core *__clk_set_parent_before(struct clk_core *core,
struct clk_core *parent)
{
@@ -1803,6 +1965,10 @@ static struct clk_core *__clk_set_parent_before(struct clk_core *core,
* See also: Comment for clk_set_parent() below.
*/
+/*
+ * IAMROOT, 2022.08.13:
+ * - CLK_OPS_PARENT_ENABLE이 있는경우 old_parent와 parent를 prepare/enable 한다.
+ */
/* enable old_parent & parent if CLK_OPS_PARENT_ENABLE is set */
if (core->flags & CLK_OPS_PARENT_ENABLE) {
clk_core_prepare_enable(old_parent);
@@ -1810,6 +1976,10 @@ static struct clk_core *__clk_set_parent_before(struct clk_core *core,
}
/* migrate prepare count if > 0 */
+/*
+ * IAMROOT, 2022.08.13:
+ * - 현재 core가 prepare 되있는 상태라면 parent를 prepare/enable하고 core도 enable한다.
+ */
if (core->prepare_count) {
clk_core_prepare_enable(parent);
clk_core_enable_lock(core);
@@ -1823,6 +1993,10 @@ static struct clk_core *__clk_set_parent_before(struct clk_core *core,
return old_parent;
}
+/*
+ * IAMROOT, 2022.08.13:
+ * - 필요없어진 clk을 diable/unprepare
+ */
static void __clk_set_parent_after(struct clk_core *core,
struct clk_core *parent,
struct clk_core *old_parent)
@@ -1919,6 +2093,10 @@ static int __clk_speculate_rates(struct clk_core *core,
return ret;
}
+/*
+ * IAMROOT, 2022.08.13:
+ * - 결정된 new_rate, new_parent, p_index을 subtree 재귀로 넣어준다.
+ */
static void clk_calc_subtree(struct clk_core *core, unsigned long new_rate,
struct clk_core *new_parent, u8 p_index)
{
@@ -1929,9 +2107,17 @@ static void clk_calc_subtree(struct clk_core *core, unsigned long new_rate,
core->new_parent_index = p_index;
/* include clk in new parent's PRE_RATE_CHANGE notifications */
core->new_child = NULL;
+/*
+ * IAMROOT, 2022.08.13:
+ * - 현재 parent랑 같이 않으면 child도 이동을 해야되므로 new_child로 set해놓는다.
+ */
if (new_parent && new_parent != core->parent)
new_parent->new_child = core;
+/*
+ * IAMROOT, 2022.08.13:
+ * - chlid 가 parent가 되어 재귀로 new를 설정하러 간다.
+ */
hlist_for_each_entry(child, &core->children, child_node) {
child->new_rate = clk_recalc(child, new_rate);
clk_calc_subtree(child, child->new_rate, NULL, 0);
@@ -1942,6 +2128,11 @@ static void clk_calc_subtree(struct clk_core *core, unsigned long new_rate,
* calculate the new rates returning the topmost clock that has to be
* changed.
*/
+/*
+ * IAMROOT, 2022.08.13:
+ * - tree를 재귀로 돌며 @rate를 설정할수있는 new_rate, new_parent, new_child를
+ * 찾아서 얻어온다.
+ */
static struct clk_core *clk_calc_new_rates(struct clk_core *core,
unsigned long rate)
{
@@ -1966,6 +2157,10 @@ static struct clk_core *clk_calc_new_rates(struct clk_core *core,
clk_core_get_boundaries(core, &min_rate, &max_rate);
/* find the closest rate and parent clk/rate */
+/*
+ * IAMROOT, 2022.08.13:
+ * - round로 구해올수있으면 round기능으로 rate를 구해온다.
+ */
if (clk_core_can_round(core)) {
struct clk_rate_request req;
@@ -1986,10 +2181,18 @@ static struct clk_core *clk_calc_new_rates(struct clk_core *core,
if (new_rate < min_rate || new_rate > max_rate)
return NULL;
} else if (!parent || !(core->flags & CLK_SET_RATE_PARENT)) {
+/*
+ * IAMROOT, 2022.08.13:
+ * - parent가 없거나 parent가 있어도 parent로 올라갈수없으면 자기것으로 설정후 return.
+ */
/* pass-through clock without adjustable parent */
core->new_rate = core->rate;
return NULL;
} else {
+/*
+ * IAMROOT, 2022.08.13:
+ * - parent가 있고 CLK_SET_RATE_PARENT가 가능한 상태. 재귀로 parent에서 시도해본다.
+ */
/* pass-through clock with adjustable parent */
top = clk_calc_new_rates(parent, rate);
new_rate = parent->new_rate;
@@ -1997,6 +2200,10 @@ static struct clk_core *clk_calc_new_rates(struct clk_core *core,
}
/* some clocks must be gated to change parent */
+/*
+ * IAMROOT, 2022.08.13:
+ * - gate가 열려 있는 상태. 사용중이 상태이기때문에 바꾸지 못한다.
+ */
if (parent != old_parent &&
(core->flags & CLK_SET_PARENT_GATE) && core->prepare_count) {
pr_debug("%s: %s not gated but wants to reparent\n",
@@ -2005,6 +2212,10 @@ static struct clk_core *clk_calc_new_rates(struct clk_core *core,
}
/* try finding the new parent index */
+/*
+ * IAMROOT, 2022.08.13:
+ * - parent가 여러개인경우 @parent의 index를 구해온다.
+ */
if (parent && core->num_parents > 1) {
p_index = clk_fetch_parent_index(core, parent);
if (p_index < 0) {
@@ -2014,6 +2225,10 @@ static struct clk_core *clk_calc_new_rates(struct clk_core *core,
}
}
+/*
+ * IAMROOT, 2022.08.13:
+ * - parent rate랑 best랑 일치하지 않으면 best로 변경을 시도한다.(재귀)
+ */
if ((core->flags & CLK_SET_RATE_PARENT) && parent &&
best_parent_rate != parent->rate)
top = clk_calc_new_rates(parent, best_parent_rate);
@@ -2029,6 +2244,11 @@ static struct clk_core *clk_calc_new_rates(struct clk_core *core,
* so that in case of an error we can walk down the whole tree again and
* abort the change.
*/
+/*
+ * IAMROOT, 2022.08.13:
+ * @event PRE_RATE_CHANGE등.
+ * - 재귀로 @event를 전달한다.
+ */
static struct clk_core *clk_propagate_rate_change(struct clk_core *core,
unsigned long event)
{
@@ -2039,11 +2259,19 @@ static struct clk_core *clk_propagate_rate_change(struct clk_core *core,
return NULL;
if (core->notifier_count) {
+/*
+ * IAMROOT, 2022.08.13:
+ * - clk notifier들한테 전달한다.
+ */
ret = __clk_notify(core, event, core->rate, core->new_rate);
if (ret & NOTIFY_STOP_MASK)
fail_clk = core;
}
+/*
+ * IAMROOT, 2022.08.13:
+ * - child한태도 event를 전달한다.
+ */
hlist_for_each_entry(child, &core->children, child_node) {
/* Skip children who will be reparented to another clock */
if (child->new_parent && child->new_parent != core)
@@ -2054,6 +2282,10 @@ static struct clk_core *clk_propagate_rate_change(struct clk_core *core,
}
/* handle the new child who might not be in core->children yet */
+/*
+ * IAMROOT, 2022.08.13:
+ * - new child한테도 보낸다.
+ */
if (core->new_child) {
tmp_clk = clk_propagate_rate_change(core->new_child, event);
if (tmp_clk)
@@ -2067,6 +2299,11 @@ static struct clk_core *clk_propagate_rate_change(struct clk_core *core,
* walk down a subtree and set the new rates notifying the rate
* change on the way
*/
+/*
+ * IAMROOT, 2022.08.13:
+ * - 실제 parent 변경 및 하드웨어적인 clk on, rate 설정.
+ * 재귀로 child를 순회하며 조작한다.
+ */
static void clk_change_rate(struct clk_core *core)
{
struct clk_core *child;
@@ -2079,6 +2316,10 @@ static void clk_change_rate(struct clk_core *core)
old_rate = core->rate;
+/*
+ * IAMROOT, 2022.08.13:
+ * - new_parent가 있으면 new_parent를 사용. 아니면 parent를 사용.
+ */
if (core->new_parent) {
parent = core->new_parent;
best_parent_rate = core->new_parent->rate;
@@ -2095,10 +2336,22 @@ static void clk_change_rate(struct clk_core *core)
clk_core_enable_lock(core);
}
+/*
+ * IAMROOT, 2022.08.13:
+ * - mux clk에 대한 조작.
+ */
if (core->new_parent && core->new_parent != core->parent) {
+/*
+ * IAMROOT, 2022.08.13:
+ * - @core의 parent을 실제적으로 변경한다.
+ */
old_parent = __clk_set_parent_before(core, core->new_parent);
trace_clk_set_parent(core, core->new_parent);
+/*
+ * IAMROOT, 2022.08.13:
+ * - 현재 clk의 parent(입력소스) 및 rate를 변경한다.
+ */
if (core->ops->set_rate_and_parent) {
skip_set_rate = true;
core->ops->set_rate_and_parent(core->hw, core->new_rate,
@@ -2117,11 +2370,19 @@ static void clk_change_rate(struct clk_core *core)
trace_clk_set_rate(core, core->new_rate);
+/*
+ * IAMROOT, 2022.08.13:
+ * - rate clock 조작.
+ */
if (!skip_set_rate && core->ops->set_rate)
core->ops->set_rate(core->hw, core->new_rate, best_parent_rate);
trace_clk_set_rate_complete(core, core->new_rate);
+/*
+ * IAMROOT, 2022.08.13:
+ * - 최종 rate를 산출한다.
+ */
core->rate = clk_recalc(core, best_parent_rate);
if (core->flags & CLK_SET_RATE_UNGATE) {
@@ -2132,6 +2393,11 @@ static void clk_change_rate(struct clk_core *core)
if (core->flags & CLK_OPS_PARENT_ENABLE)
clk_core_disable_unprepare(parent);
+/*
+ * IAMROOT, 2022.08.13:
+ * - 실제 적용.
+ * - 모든 clk설정에 문제가 없으면 적용한다.
+ */
if (core->notifier_count && old_rate != core->rate)
__clk_notify(core, POST_RATE_CHANGE, old_rate, core->rate);
@@ -2142,6 +2408,10 @@ static void clk_change_rate(struct clk_core *core)
* Use safe iteration, as change_rate can actually swap parents
* for certain clock types.
*/
+/*
+ * IAMROOT, 2022.08.13:
+ * - 재귀로 child를 순회하며 변경한다.
+ */
hlist_for_each_entry_safe(child, tmp, &core->children, child_node) {
/* Skip children who will be reparented to another clock */
if (child->new_parent && child->new_parent != core)
@@ -2195,6 +2465,10 @@ static int clk_core_set_rate_nolock(struct clk_core *core,
rate = clk_core_req_round_rate_nolock(core, req_rate);
+/*
+ * IAMROOT, 2022.08.13:
+ * - @core의 현재 rate가 rate랑 일치하면 return.
+ */
/* bail early if nothing to do */
if (rate == clk_core_get_rate_nolock(core))
return 0;
@@ -2204,6 +2478,10 @@ static int clk_core_set_rate_nolock(struct clk_core *core,
return -EBUSY;
/* calculate new rates and get the topmost changed clock */
+/*
+ * IAMROOT, 2022.08.13:
+ * - @req_rate를 set할수있는 new 값들을 구해온다.
+ */
top = clk_calc_new_rates(core, req_rate);
if (!top)
return -EINVAL;
@@ -2212,6 +2490,10 @@ static int clk_core_set_rate_nolock(struct clk_core *core,
if (ret)
return ret;
+/*
+ * IAMROOT, 2022.08.13:
+ * - 이전에 구한 new값으로 변경 가능한지 물어본다.(실제 설정은 안한다.) 안되면 롤백.
+ */
/* notify that we are about to change rates */
fail_clk = clk_propagate_rate_change(top, PRE_RATE_CHANGE);
if (fail_clk) {
@@ -2222,6 +2504,10 @@ static int clk_core_set_rate_nolock(struct clk_core *core,
goto err;
}
+/*
+ * IAMROOT, 2022.08.13:
+ * - 잘 바뀌면. 실제 change
+ */
/* change the rates */
clk_change_rate(top);
@@ -3473,6 +3759,13 @@ static void clk_core_reparent_orphans_nolock(void)
* Initializes the lists in struct clk_core, queries the hardware for the
* parent and rate and sets them both.
*/
+/*
+ * IAMROOT, 2022.08.13:
+ * - 1. ops 검사.
+ * 2. parent가 없는 @core면 root.
+ * parent가 있는데 parent가 아직 등록안됬으면 orphan.
+ * parent가 있는데 parent가 있으면 parent에 등록.
+ */
static int __clk_core_init(struct clk_core *core)
{
int ret;
@@ -3483,12 +3776,24 @@ static int __clk_core_init(struct clk_core *core)
if (!core)
return -EINVAL;
+/*
+ * IAMROOT, 2022.08.13:
+ * - lock.
+ */
clk_prepare_lock();
+/*
+ * IAMROOT, 2022.08.13:
+ * - 절전모드였을 경우 다시 power on
+ */
ret = clk_pm_runtime_get(core);
if (ret)
goto unlock;
+/*
+ * IAMROOT, 2022.08.13:
+ * - core를 찾는다.
+ */
/* check to see if a clock with this name is already registered */
if (clk_core_lookup(core->name)) {
pr_debug("%s: clk %s already initialized\n",
@@ -3497,7 +3802,18 @@ static int __clk_core_init(struct clk_core *core)
goto out;
}
+/*
+ * IAMROOT, 2022.08.13:
+ * - ops를 전체적으로 잘 설정되있는지 검사한다.
+ */
/* check that clk_ops are sane. See Documentation/driver-api/clk.rst */
+/*
+ * IAMROOT, 2022.08.13:
+ * - set_rate가 지정되면 round_rate, determine_rate 둘중하나와
+ * recalc_rate가 존재해야된다.
+ * 설정을 못하는 clk이 왔을때 대처방안을 마련해줘야되는 개념.
+ * ex) clk_factor_round_rate, clk_factor_set_rate, clk_factor_recalc_rate,
+ */
if (core->ops->set_rate &&
!((core->ops->round_rate || core->ops->determine_rate) &&
core->ops->recalc_rate)) {
@@ -3577,9 +3893,17 @@ static int __clk_core_init(struct clk_core *core)
hlist_add_head(&core->child_node, &parent->children);
core->orphan = parent->orphan;
} else if (!core->num_parents) {
+/*
+ * IAMROOT, 2022.08.13:
+ * - 최상위 fixed factor면 root로 등록한다.
+ */
hlist_add_head(&core->child_node, &clk_root_list);
core->orphan = false;
} else {
+/*
+ * IAMROOT, 2022.08.13:
+ * - parent가 있는데 . 못찾은경우.(아직 parent가 등록안되있음.). orphan.
+ */
hlist_add_head(&core->child_node, &clk_orphan_list);
core->orphan = true;
}
@@ -3836,6 +4160,11 @@ static int clk_cpy_name(const char **dst_p, const char *src, bool must_exist)
return 0;
}
+/*
+ * IAMROOT, 2022.08.13:
+ * - parent_xxx 인자에 따라 core의 parent를 설정한다.
+ * 각각의 parent index는 -1로 설정해놓는다. 아직 연결이 안되있다는 의미.
+ */
static int clk_core_populate_parent_map(struct clk_core *core,
const struct clk_init_data *init)
{
@@ -3846,9 +4175,17 @@ static int clk_core_populate_parent_map(struct clk_core *core,
int i, ret = 0;
struct clk_parent_map *parents, *parent;
+/*
+ * IAMROOT, 2022.08.13:
+ * - parent가 없으면 빠져나간다.
+ */
if (!num_parents)
return 0;
+/*
+ * IAMROOT, 2022.08.13:
+ * - parent가 있을 경우.
+ */
/*
* Avoid unnecessary string look-ups of clk_core's possible parents by
* having a cache of names/clk_hw pointers to clk_core pointers.
@@ -3861,6 +4198,18 @@ static int clk_core_populate_parent_map(struct clk_core *core,
/* Copy everything over because it might be __initdata */
for (i = 0, parent = parents; i < num_parents; i++, parent++) {
parent->index = -1;
+
+/*
+ * IAMROOT, 2022.08.13:
+ * - 상위 함수에 따라 parent_name, parent_data, parent_hw 3가지중 한가지가
+ * 무조건 있을 것이다.
+ * - parent_name
+ * name만 copy한다.
+ * - parent_data
+ * hw, index, name(fw_name으로 copy)을 설정한다.
+ * - parent_hw
+ * hw만 설정한다.
+ */
if (parent_names) {
/* throw a WARN if any entries are NULL */
WARN(!parent_names[i],
@@ -3915,7 +4264,8 @@ static void clk_core_free_parent_map(struct clk_core *core)
/*
* IAMROOT, 2022.08.06:
- * - @hw로 받은 data로 core와 clk를 생성한다.
+ * - @hw로 받은 data로 core와 clk를 생성하고,
+ * root list or orphan list, 부모의 child 에 등록한다.
*/
static struct clk *
__clk_register(struct device *dev, struct device_node *np, struct clk_hw *hw)
@@ -3962,6 +4312,10 @@ __clk_register(struct device *dev, struct device_node *np, struct clk_hw *hw)
core->max_rate = ULONG_MAX;
hw->core = core;
+/*
+ * IAMROOT, 2022.08.13:
+ * - core의 parent map 할당 및 초기화.
+ */
ret = clk_core_populate_parent_map(core, init);
if (ret)
goto fail_parents;
@@ -3972,6 +4326,11 @@ __clk_register(struct device *dev, struct device_node *np, struct clk_hw *hw)
* Don't call clk_hw_create_clk() here because that would pin the
* provider module to itself and prevent it from ever being removed.
*/
+
+/*
+ * IAMROOT, 2022.08.13:
+ * - clk 자료구조 설정.
+ */
hw->clk = alloc_clk(core, NULL, NULL);
if (IS_ERR(hw->clk)) {
ret = PTR_ERR(hw->clk);
@@ -3987,6 +4346,10 @@ __clk_register(struct device *dev, struct device_node *np, struct clk_hw *hw)
*/
clk_core_link_consumer(hw->core, hw->clk);
+/*
+ * IAMROOT, 2022.08.13:
+ * - core를 등록한다.
+ */
ret = __clk_core_init(core);
if (!ret)
return hw->clk;
@@ -4082,6 +4445,12 @@ EXPORT_SYMBOL_GPL(clk_hw_register);
* less than zero indicating failure. Drivers must test for an error code after
* calling of_clk_hw_register().
*/
+
+/*
+ * IAMROOT, 2022.08.06:
+ * - @hw로 받은 data로 core와 clk를 생성하고,
+ * root list or orphan list, 부모의 child 에 등록한다.
+ */
int of_clk_hw_register(struct device_node *node, struct clk_hw *hw)
{
return PTR_ERR_OR_ZERO(__clk_register(NULL, node, hw));
@@ -4459,6 +4828,10 @@ void __clk_put(struct clk *clk)
* allocation failure; otherwise, passes along the return value of
* srcu_notifier_chain_register().
*/
+/*
+ * IAMROOT, 2022.08.13:
+ * - @clk에 해당하는 @nb를 clk_notifier_list에 등록한다.
+ */
int clk_notifier_register(struct clk *clk, struct notifier_block *nb)
{
struct clk_notifier *cn;
@@ -4470,10 +4843,19 @@ int clk_notifier_register(struct clk *clk, struct notifier_block *nb)
clk_prepare_lock();
/* search the list of notifiers for this clk */
+/*
+ * IAMROOT, 2022.08.13:
+ * - 이미 있는지 찾는다.
+ */
list_for_each_entry(cn, &clk_notifier_list, node)
if (cn->clk == clk)
goto found;
+/*
+ * IAMROOT, 2022.08.13:
+ * - 없다면 메모리를 할당하고 초기화한후 clk_notifier_list에 넣고 notifier_count를
+ * 증가시킨다.
+ */
/* if clk wasn't in the notifier list, allocate new clk_notifier */
cn = kzalloc(sizeof(*cn), GFP_KERNEL);
if (!cn)
@@ -5055,8 +5437,8 @@ EXPORT_SYMBOL_GPL(of_clk_get_from_provider);
/*
* IAMROOT, 2022.08.06:
- * - @np에서 @index, @name에 해당하는 clock을 찾은후 of_clk_providers에서 일치하는게
- * 있는지 확인한다.
+ * - @np에서 @index, @con_id에 해당하는 clock을 찾은후
+ * of_clk_providers에서 일치하는게 있는지 확인한다.
*/
struct clk_hw *of_clk_get_hw(struct device_node *np, int index,
const char *con_id)
@@ -5067,7 +5449,7 @@ struct clk_hw *of_clk_get_hw(struct device_node *np, int index,
/*
* IAMROOT, 2022.08.06:
- * - @index or @name에 해당하는 clock을 phandle argu를 가져온다.
+ * - @index or @con_id에 해당하는 clock을 phandle argu를 가져온다.
*/
ret = of_parse_clkspec(np, index, con_id, &clkspec);
if (ret)
@@ -5134,6 +5516,12 @@ EXPORT_SYMBOL(of_clk_get_by_name);
*
* Returns: The number of clocks that are possible parents of this node
*/
+
+/*
+ * IAMROOT, 2022.08.13:
+ * - clocks의 입력소스가 몇개잇ㅎ는지 알아온다.
+ * ex) clocks = <&a>, <&b> => 2개.
+ */
unsigned int of_clk_get_parent_count(const struct device_node *np)
{
int count;
@@ -5146,6 +5534,10 @@ unsigned int of_clk_get_parent_count(const struct device_node *np)
}
EXPORT_SYMBOL_GPL(of_clk_get_parent_count);
+/*
+ * IAMROOT, 2022.08.13:
+ * - @index에 해당하는 clk의 parent name을 가져온다.
+ */
const char *of_clk_get_parent_name(const struct device_node *np, int index)
{
struct of_phandle_args clkspec;
@@ -5157,17 +5549,41 @@ const char *of_clk_get_parent_name(const struct device_node *np, int index)
int count;
struct clk *clk;
+/*
+ * IAMROOT, 2022.08.13:
+ * - index에 해당하는 phandle을 가져온다.
+ * ex) clocks = <&a ..> <&b ..>
+ * index == 0이면 <&a ..>에 대한 phandle 가져온다.
+ */
rc = of_parse_phandle_with_args(np, "clocks", "#clock-cells", index,
&clkspec);
if (rc)
return NULL;
+/*
+ * IAMROOT, 2022.08.13:
+ * - clocks = <&a 2> <&b 3>
+ * index = 0 요청 이라고 했을때
+ * &a 2가 선택되고 여기서 args[0]는 2가 되어
+ * index = 2가 된다.
+ */
index = clkspec.args_count ? clkspec.args[0] : 0;
count = 0;
/* if there is an indices property, use it to transfer the index
* specified into an array offset for the clock-output-names property.
*/
+/*
+ * IAMROOT, 2022.08.13:
+ * - parent np에서 clock-indices로 index를 변경해야되는지 확인한다.
+ *
+ * - clock-indices = <3> <5>
+ * index 번호를 바꾼다는것.
+ * ex) clocks = <&a ..> <&b ..>
+ * clock-indices = <3> <5>
+ * a가 index = 0 -> 3, b가 index 1 -> 5로 바뀌게되는것이고 이 후 바뀐
+ * index로 접근해야된다.
+ */
of_property_for_each_u32(clkspec.np, "clock-indices", prop, vp, pv) {
if (index == pv) {
index = count;
@@ -5179,6 +5595,12 @@ const char *of_clk_get_parent_name(const struct device_node *np, int index)
if (prop && !vp)
return NULL;
+/*
+ * IAMROOT, 2022.08.13:
+ * - parent np에서 정해진 이름이 있는지 확인한다.
+ *
+ * - index로 안하고 문자열로 찾고싶을때 사용.
+ */
if (of_property_read_string_index(clkspec.np, "clock-output-names",
index,
&clk_name) < 0) {
@@ -5188,6 +5610,11 @@ const char *of_clk_get_parent_name(const struct device_node *np, int index)
* registered, we return the node name as the name of
* the clock as long as #clock-cells = 0.
*/
+/*
+ * IAMROOT, 2022.08.13:
+ * - 실패했거나 clock-output-names가 없는경우엔 clkspec로 등록된 provider에서
+ * 찾아서 clk_name을 설정한다.
+ */
clk = of_clk_get_from_provider(&clkspec);
if (IS_ERR(clk)) {
if (clkspec.args_count == 0)
@@ -5215,6 +5642,10 @@ EXPORT_SYMBOL_GPL(of_clk_get_parent_name);
*
* Return: number of parents for the clock node.
*/
+/*
+ * IAMROOT, 2022.08.13:
+ * - @np의 @size(parent 개수)만큼 순회해서 parents에 parent name을 채운다.
+ */
int of_clk_parent_fill(struct device_node *np, const char **parents,
unsigned int size)
{
@@ -5405,8 +5836,27 @@ void __init of_clk_init(const struct of_device_id *matches)
/*
* IAMROOT, 2022.08.06:
- * - of_fixed_clk_setup 참고. of_clk_providers에 등록된다.
+ * - of_fixed_clk_setup(fixed rate등록). 참고.
+ * of_fixed_factor_clk_setup(fixed factor등록),
+ * of_clk_providers에 등록된다.
* - of_clk_add_hw_provider이나 of_clk_add_provider를 통해서 등록될것이다.
+ *
+ * ex)
+ * 읽힌 순서 | 3 2 1
+ * tree 순서 | A -> B -> C
+ *
+ * step 1) C가 orphan으로 들어간다.
+ * root |
+ * orphan | C
+ *
+ * step 2) B가 orphan으로 들어가고, C는 B의 child로 들어간다.
+ * root |
+ * orphan | B
+ *
+ * step 3) A가 root로 들어가고, orphan list 검색을 통해 B가 A의 child로 들어가
+ * 완성된다.
+ * root | A
+ * orphan |
*/
clk_provider->clk_init_cb(clk_provider->np);
of_clk_set_defaults(clk_provider->np, true);
diff --git a/drivers/clk/clkdev.c b/drivers/clk/clkdev.c
index 67f601a41023..a0f74cc681d8 100644
--- a/drivers/clk/clkdev.c
+++ b/drivers/clk/clkdev.c
@@ -33,6 +33,10 @@ static DEFINE_MUTEX(clocks_mutex);
* Then we take the most specific entry - with the following
* order of precedence: dev+con > dev only > con only.
*/
+/*
+ * IAMROOT, 2022.08.13:
+ * - dev+con > dev only > con only 순으로 찾아본다.
+ */
static struct clk_lookup *clk_find(const char *dev_id, const char *con_id)
{
struct clk_lookup *p, *cl = NULL;
@@ -47,17 +51,31 @@ static struct clk_lookup *clk_find(const char *dev_id, const char *con_id)
list_for_each_entry(p, &clocks, node) {
match = 0;
+
+/*
+ * IAMROOT, 2022.08.13:
+ * - dev_id 일치하면 2 point
+ */
if (p->dev_id) {
if (!dev_id || strcmp(p->dev_id, dev_id))
continue;
match += 2;
}
+
+/*
+ * IAMROOT, 2022.08.13:
+ * - con_id 일치하면 1 point
+ */
if (p->con_id) {
if (!con_id || strcmp(p->con_id, con_id))
continue;
match += 1;
}
+/*
+ * IAMROOT, 2022.08.13:
+ * - 주어진 인자와 일치하게 point가 얻어지면 바로 break. 아니면 best로 갱신한다.
+ */
if (match > best_found) {
cl = p;
if (match != best_possible)
@@ -69,11 +87,21 @@ static struct clk_lookup *clk_find(const char *dev_id, const char *con_id)
return cl;
}
+/*
+ * IAMROOT, 2022.08.13:
+ * - dt를 사용하지 않은 lagacy에서는 custom방식으로 등록을 이미 시켜놨다.
+ * clokcs(drivers/clk/clkdev.c) 전역변수에서 바로 찾는다.
+ */
struct clk_hw *clk_find_hw(const char *dev_id, const char *con_id)
{
struct clk_lookup *cl;
struct clk_hw *hw = ERR_PTR(-ENOENT);
+/*
+ * IAMROOT, 2022.08.13:
+ * - clocks(drivers/clk/clkdev.c) 전역리스트에서 dev_id, con_id로 검색해본다.
+ * dev_id + con_id > dev_id > con_id로 우선순위되서 찾는다.
+ */
mutex_lock(&clocks_mutex);
cl = clk_find(dev_id, con_id);
if (cl)
@@ -83,6 +111,11 @@ struct clk_hw *clk_find_hw(const char *dev_id, const char *con_id)
return hw;
}
+/*
+ * IAMROOT, 2022.08.13:
+ * - @dev_id, @con_id에 따라서 hw을 찾아오고 clk자료 구조를 생성해
+ * clk에 dev를 등록하고 core와 clk를 연결한다.
+ */
static struct clk *__clk_get_sys(struct device *dev, const char *dev_id,
const char *con_id)
{
@@ -91,23 +124,45 @@ static struct clk *__clk_get_sys(struct device *dev, const char *dev_id,
return clk_hw_create_clk(dev, hw, dev_id, con_id);
}
+
+/*
+ * IAMROOT, 2022.08.13:
+ * - @dev_id, @con_id에 따라서 hw을 찾아오고 clk자료 구조를 생성해
+ * core와 clk를 연결한다.
+ */
struct clk *clk_get_sys(const char *dev_id, const char *con_id)
{
return __clk_get_sys(NULL, dev_id, con_id);
}
EXPORT_SYMBOL(clk_get_sys);
+/*
+ * IAMROOT, 2022.08.13:
+ * @dev consumer측의 device
+ * @con_id @dev와 연결될것.
+ * - dt나 system 방식으로 dev_id, con_id로 검색해 hw를 찾아서 등록한다.
+ */
struct clk *clk_get(struct device *dev, const char *con_id)
{
const char *dev_id = dev ? dev_name(dev) : NULL;
struct clk_hw *hw;
+/*
+ * IAMROOT, 2022.08.13:
+ * - dt에서 왔으면(dev->of_node가 있다는것.) of_clk_get_hw로 들어간다.
+ * dts에서 phandle을 찾고, 해당 정보로 연결된 clk core에 clk(consumer)
+ * 를 만들어서 등록한다.
+ */
if (dev && dev->of_node) {
hw = of_clk_get_hw(dev->of_node, 0, con_id);
if (!IS_ERR(hw) || PTR_ERR(hw) == -EPROBE_DEFER)
return clk_hw_create_clk(dev, hw, dev_id, con_id);
}
+/*
+ * IAMROOT, 2022.08.13:
+ * - dt가 아니였거나 error 였을경우 실행.
+ */
return __clk_get_sys(dev, dev_id, con_id);
}
EXPORT_SYMBOL(clk_get);
diff --git a/drivers/clk/qcom/kpss-xcc.c b/drivers/clk/qcom/kpss-xcc.c
index 8590b5edd19d..d621041af203 100644
--- a/drivers/clk/qcom/kpss-xcc.c
+++ b/drivers/clk/qcom/kpss-xcc.c
@@ -29,6 +29,17 @@ static const struct of_device_id kpss_xcc_match_table[] = {
};
MODULE_DEVICE_TABLE(of, kpss_xcc_match_table);
+
+/*
+ * IAMROOT, 2022.08.13:
+ * ex)
+ * acc0: clock-controller@2088000 {
+ * compatible = "qcom,kpss-acc-v1";
+ * reg = <0x02088000 0x1000>, <0x02008000 0x1000>;
+ * };
+ *
+ * - table 등록.
+ */
static int kpss_xcc_driver_probe(struct platform_device *pdev)
{
const struct of_device_id *id;
diff --git a/drivers/clk/ti/composite.c b/drivers/clk/ti/composite.c
index eaa43575cfa5..650cdc109961 100644
--- a/drivers/clk/ti/composite.c
+++ b/drivers/clk/ti/composite.c
@@ -239,6 +239,10 @@ CLK_OF_DECLARE(ti_composite_clock, "ti,composite-clock",
* Adds a component clock to the list of available components, so that
* it can be registered by a composite clock.
*/
+/*
+ * IAMROOT, 2022.08.13:
+ * - clk를 생성해 parent clk정보를 찾아서 등록하고, @type으로 설정한다.
+ */
int __init ti_clk_add_component(struct device_node *node, struct clk_hw *hw,
int type)
{
@@ -257,6 +261,10 @@ int __init ti_clk_add_component(struct device_node *node, struct clk_hw *hw,
if (!parent_names)
return -ENOMEM;
+/*
+ * IAMROOT, 2022.08.13:
+ * - dt에서 parent_names를 num_parents만큼 가져온다.
+ */
of_clk_parent_fill(node, parent_names, num_parents);
clk = kzalloc(sizeof(*clk), GFP_KERNEL);
diff --git a/drivers/clk/ti/divider.c b/drivers/clk/ti/divider.c
index 28080df92f72..02bee393a47a 100644
--- a/drivers/clk/ti/divider.c
+++ b/drivers/clk/ti/divider.c
@@ -76,6 +76,12 @@ static unsigned int _get_div(struct clk_omap_divider *divider, unsigned int val)
return val + 1;
}
+/*
+ * IAMROOT, 2022.08.13:
+ * - @div가 table에 있어야 해당 val을 가져온다.
+ * - ex) ti,dividers = <8>, <16>;
+ * div == 8이면 return 0. div == 16이면 return 1
+ */
static unsigned int _get_table_val(const struct clk_div_table *table,
unsigned int div)
{
@@ -87,14 +93,32 @@ static unsigned int _get_table_val(const struct clk_div_table *table,
return 0;
}
+/*
+ * IAMROOT, 2022.08.13:
+ * - 4가지 방식으로 div를 구해온다.
+ * ex) parent 16MHz, 요구 1Mhz 일때 div. 16인 상황.
+ * 1) CLK_DIVIDER_ONE_BASED. : return 16
+ * 2) CLK_DIVIDER_POWER_OF_TWO : return 4
+ * 3) divider->table : table에 <8>, <16>을 썻다고 가정. return 1
+ * 4) div - 1 : return 15
+ */
static unsigned int _get_val(struct clk_omap_divider *divider, u8 div)
{
if (divider->flags & CLK_DIVIDER_ONE_BASED)
return div;
if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
return __ffs(div);
+/*
+ * IAMROOT, 2022.08.13:
+ * ex) 1/1, 1/3, 1/57.. 와 같이 불규칙한 하드웨어면 table에 해당 divide를 정의해서
+ * 사용하는 방식으로 쓴다.
+ */
if (divider->table)
return _get_table_val(divider->table, div);
+/*
+ * IAMROOT, 2022.08.13:
+ * - -1만 한다.
+ */
return div - 1;
}
@@ -261,6 +285,12 @@ static int ti_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
value = _get_val(divider, div);
+/*
+ * IAMROOT, 2022.08.13:
+ * - read register.
+ * set register value.
+ * write register
+ */
val = ti_clk_ll_ops->clk_readl(÷r->reg);
val &= ~(divider->mask << divider->shift);
val |= value << divider->shift;
@@ -392,6 +422,17 @@ int ti_clk_parse_divider_data(int *div_table, int num_dividers, int max_div,
return 0;
}
+/*
+ * IAMROOT, 2022.08.13:
+ * - ex)
+ * abe_24m_fclk: abe_24m_fclk@11c {
+ * #clock-cells = <0>;
+ * compatible = "ti,divider-clock";
+ * clocks = <&dpll_abe_m2x2_ck>;
+ * reg = <0x011c>;
+ * ti,dividers = <8>, <16>;
+ * };
+ */
static int __init ti_clk_get_div_table(struct device_node *node,
struct clk_omap_divider *div)
{
@@ -550,6 +591,10 @@ static void __init of_ti_divider_clk_setup(struct device_node *node)
}
CLK_OF_DECLARE(divider_clk, "ti,divider-clock", of_ti_divider_clk_setup);
+/*
+ * IAMROOT, 2022.08.13:
+ * - CLK_COMPONENT_TYPE_DIVIDER로 add한다.
+ */
static void __init of_ti_composite_divider_clk_setup(struct device_node *node)
{
struct clk_omap_divider *div;
diff --git a/drivers/clk/ti/mux.c b/drivers/clk/ti/mux.c
index 0069e7cf3ebc..017d1cf47fa8 100644
--- a/drivers/clk/ti/mux.c
+++ b/drivers/clk/ti/mux.c
@@ -63,6 +63,11 @@ static u8 ti_clk_mux_get_parent(struct clk_hw *hw)
return val;
}
+/*
+ * IAMROOT, 2022.08.13:
+ * - table방식이면 table[index]에서 실제 index값을 가져오고
+ * 아니면 index를 flag에 따라 가져온다.
+ */
static int ti_clk_mux_set_parent(struct clk_hw *hw, u8 index)
{
struct clk_omap_mux *mux = to_clk_omap_mux(hw);
@@ -118,6 +123,12 @@ static void clk_mux_restore_context(struct clk_hw *hw)
ti_clk_mux_set_parent(hw, mux->saved_parent);
}
+/*
+ * IAMROOT, 2022.08.13:
+ * - set_rate가 없는 이유.
+ * mux이기 때문에 parent에서 선택해서 바꿔야된다. 즉 mux는 get_parent, set_parent
+ * 가 기본이 된다.
+ */
const struct clk_ops ti_clk_mux_ops = {
.get_parent = ti_clk_mux_get_parent,
.set_parent = ti_clk_mux_set_parent,
@@ -254,6 +265,19 @@ struct clk_hw *ti_clk_build_component_mux(struct ti_clk_mux *setup)
return &mux->hw;
}
+/*
+ * IAMROOT, 2022.08.13:
+ * - ti가 가장 뼈대가 되는 mux driver를 만듬.
+ * - ex) arm/boot/dts/am33xx-clocks.dtsi
+ * sys_clkin_ck: sys_clkin_ck@40 {
+ * #clock-cells = <0>;
+ * compatible = "ti,mux-clock";
+ * clocks = <&virt_19200000_ck>, <&virt_24000000_ck>,
+ * <&virt_25000000_ck>, <&virt_26000000_ck>;
+ * ti,bit-shift = <22>;
+ * reg = <0x0040>;
+ * };
+ */
static void __init of_ti_composite_mux_clk_setup(struct device_node *node)
{
struct clk_omap_mux *mux;
@@ -270,11 +294,19 @@ static void __init of_ti_composite_mux_clk_setup(struct device_node *node)
if (!of_property_read_u32(node, "ti,bit-shift", &val))
mux->shift = val;
+/*
+ * IAMROOT, 2022.08.13:
+ * - index가 0부터 시작인지, 1부터 시작인지에 대한 여부.
+ */
if (of_property_read_bool(node, "ti,index-starts-at-one"))
mux->flags |= CLK_MUX_INDEX_ONE;
num_parents = of_clk_get_parent_count(node);
+/*
+ * IAMROOT, 2022.08.13:
+ * - mux는 2개이상이여야 한다.
+ */
if (num_parents < 2) {
pr_err("%pOFn must have parents\n", node);
goto cleanup;
@@ -283,6 +315,10 @@ static void __init of_ti_composite_mux_clk_setup(struct device_node *node)
mux->mask = num_parents - 1;
mux->mask = (1 << fls(mux->mask)) - 1;
+/*
+ * IAMROOT, 2022.08.13:
+ * - mux로 사용하겠다는 의미.
+ */
if (!ti_clk_add_component(node, &mux->hw, CLK_COMPONENT_TYPE_MUX))
return;
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 8cd3e47dd0b9..22875388b4f4 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -18,6 +18,20 @@
*/
#define CLK_SET_RATE_GATE BIT(0) /* must be gated across rate change */
#define CLK_SET_PARENT_GATE BIT(1) /* must be gated across re-parent */
+/*
+ * IAMROOT, 2022.08.13:
+ * - child, parent의 조합중에 가장 근접한 rate를 선택
+ *
+ * ex)
+ * parent divider divider device
+ * | | 1 2 4 8 | | 1 2 4 8 | | |
+ * 16MHz | ---- | ^ | ---- | ^ | ---- | 1MHz 필요 |
+ * | | | | | | |
+ * CLK_SET_RATE_PARENT
+ *
+ * device가 1MHz가 필요한 경우, 자기만의 divider만으로 해결이 안될경우
+ * parent divider까지 영향을 줘야되는 경우 CLK_SET_RATE_PARENT를 설정한다.
+ */
#define CLK_SET_RATE_PARENT BIT(2) /* propagate rate change up one level */
#define CLK_IGNORE_UNUSED BIT(3) /* do not gate even if unused */
/* unused */
@@ -403,6 +417,10 @@ struct clk *clk_register_fixed_rate(struct device *dev, const char *name,
* @fixed_rate: non-adjustable clock rate
* @fixed_accuracy: non-adjustable clock accuracy
*/
+/*
+ * IAMROOT, 2022.08.13:
+ * - fixed rate를 등록한다. parent_name으로 판단하는 경우.
+ */
#define clk_hw_register_fixed_rate_with_accuracy(dev, name, parent_name, \
flags, fixed_rate, \
fixed_accuracy) \
@@ -419,6 +437,10 @@ struct clk *clk_register_fixed_rate(struct device *dev, const char *name,
* @fixed_rate: non-adjustable clock rate
* @fixed_accuracy: non-adjustable clock accuracy
*/
+/*
+ * IAMROOT, 2022.08.13:
+ * - fixed rate를 등록한다. parent_hw으로 판단하는 경우.
+ */
#define clk_hw_register_fixed_rate_with_accuracy_parent_hw(dev, name, \
parent_hw, flags, fixed_rate, fixed_accuracy) \
__clk_hw_register_fixed_rate((dev), NULL, (name), NULL, (parent_hw) \
@@ -434,6 +456,10 @@ struct clk *clk_register_fixed_rate(struct device *dev, const char *name,
* @fixed_rate: non-adjustable clock rate
* @fixed_accuracy: non-adjustable clock accuracy
*/
+/*
+ * IAMROOT, 2022.08.13:
+ * - fixed rate를 등록한다. parent_data으로 판단하는 경우.
+ */
#define clk_hw_register_fixed_rate_with_accuracy_parent_data(dev, name, \
parent_data, flags, fixed_rate, fixed_accuracy) \
__clk_hw_register_fixed_rate((dev), NULL, (name), NULL, NULL, \
@@ -606,6 +632,13 @@ struct clk_divider {
#define clk_div_mask(width) ((1 << (width)) - 1)
#define to_clk_divider(_hw) container_of(_hw, struct clk_divider, hw)
+/*
+ * IAMROOT, 2022.08.13:
+ * - CLK_DIVIDER_ONE_BASED
+ * 1/1, 1/2, 1/3, 1/4 ...의 방식
+ * - CLK_DIVIDER_POWER_OF_TWO
+ * 1/1, 1/2, 1/4, 1/8 ..의 방식
+ */
#define CLK_DIVIDER_ONE_BASED BIT(0)
#define CLK_DIVIDER_POWER_OF_TWO BIT(1)
#define CLK_DIVIDER_ALLOW_ZERO BIT(2)
@@ -874,6 +907,12 @@ struct clk_mux {
#define to_clk_mux(_hw) container_of(_hw, struct clk_mux, hw)
+/*
+ * IAMROOT, 2022.08.13:
+ * - CLK_MUX_INDEX_ONE : 1부터 시작
+ * CLK_MUX_INDEX_BIT : 0b01, 0b10, 0b100.. 로 사용
+ * CLK_MUX_ROUND_CLOSEST : rate를 고를때 절대값의 차이가 적은것을 선택하라는것.
+ */
#define CLK_MUX_INDEX_ONE BIT(0)
#define CLK_MUX_INDEX_BIT BIT(1)
#define CLK_MUX_HIWORD_MASK BIT(2)
@@ -908,6 +947,11 @@ struct clk *clk_register_mux_table(struct device *dev, const char *name,
clk_register_mux_table((dev), (name), (parent_names), (num_parents), \
(flags), (reg), (shift), BIT((width)) - 1, \
(clk_mux_flags), NULL, (lock))
+
+/*
+ * IAMROOT, 2022.08.13:
+ * - clk_hw_register_fixed_rate류 와 비슷한 방식을 사용해서 등록한다.
+ */
#define clk_hw_register_mux_table(dev, name, parent_names, num_parents, \
flags, reg, shift, mask, clk_mux_flags, \
table, lock) \
diff --git a/include/linux/clk.h b/include/linux/clk.h
index 266e8de3cb51..f124747e3c1b 100644
--- a/include/linux/clk.h
+++ b/include/linux/clk.h
@@ -36,6 +36,20 @@ struct of_phandle_args;
* completed. Callbacks must always return NOTIFY_DONE or NOTIFY_OK.
*
*/
+/*
+ * IAMROOT, 2022.08.13:
+ * - papago
+ * PRE_RATE_CHANGE - 클럭 비율이 변경되기 직전에 호출되어 비율 변경이 계속 진행됨을
+ * 나타냅니다. 운전자는 요금 변경의 영향을 받는 모든 작업을 즉시 종료해야 합니다.
+ * 콜백은 NOTIFY_DONE, NOTIFY_OK, NOTIFY_STOP 또는 NOTIFY_BAD를 반환할 수 있습니다.
+ *
+ * ABORT_RATE_CHANGE: PRE_RATE_CHANGE 이후 어떤 이유로 비율 변경이 실패하면 호출됩니다.
+ * 이 경우 clk에 등록된 모든 알림자는 ABORT_RATE_CHANGE로 호출됩니다. 콜백은 항상
+ * NOTIFY_DONE 또는 NOTIFY_OK를 반환해야 합니다.
+ *
+ * POST_RATE_CHANGE - 클럭 비율 변경이 성공적으로 완료된 후 호출됩니다. 콜백은 항상
+ * NOTIFY_DONE 또는 NOTIFY_OK를 반환해야 합니다.
+ */
#define PRE_RATE_CHANGE BIT(0)
#define POST_RATE_CHANGE BIT(1)
#define ABORT_RATE_CHANGE BIT(2)
diff --git a/include/linux/clk/ti.h b/include/linux/clk/ti.h
index 3486f20a3753..31f644ffb9ed 100644
--- a/include/linux/clk/ti.h
+++ b/include/linux/clk/ti.h
@@ -23,6 +23,11 @@
* @offset: offset from the master IP module base address
* @index: index of the master IP module
*/
+
+/*
+ * IAMROOT, 2022.08.13:
+ * - @ptr ioremap으로 mapping한 register ptr.
+ */
struct clk_omap_reg {
void __iomem *ptr;
u16 offset;
댓글 0
번호 | 제목 | 글쓴이 | 날짜 | 조회 수 |
---|---|---|---|---|
공지 | [공지] 스터디 정리 노트 공간입니다. | woos | 2016.05.14 | 629 |
148 | [커널 17차] 103주차 | ㅇㅇㅇ | 2022.08.28 | 35 |
147 | [커널 18차] 66주차 | kkr | 2022.08.27 | 77 |
146 | [커널 17차] 101~102주차 | ㅇㅇㅇ | 2022.08.21 | 47 |
145 | [커널 18차] 65주차 | kkr | 2022.08.20 | 28 |
» | [커널 18차] 64주차 | kkr | 2022.08.13 | 75 |
143 | [커널 17차] 100주차 [1] | ㅇㅇㅇ | 2022.08.06 | 100 |
142 | [커널 18차] 63주차 | kkr | 2022.08.06 | 102 |
141 | [커널 17차] 99주차 | ㅇㅇㅇ | 2022.07.31 | 35 |
140 | [커널 18차] 62주차 | kkr | 2022.07.30 | 26 |
139 | [커널 17차] 97~98주차 | ㅇㅇㅇ | 2022.07.24 | 52 |
138 | [커널 18차] 61주차 | kkr | 2022.07.23 | 113 |
137 | [커널 18차] 60주차 | kkr | 2022.07.16 | 131 |
136 | [커널 17차] 95~96주차 | ㅇㅇㅇ | 2022.07.10 | 105 |
135 | [커널 18차] 59주차 | kkr | 2022.07.09 | 127 |
134 | [커널 19차] 8주차 | kanlee | 2022.07.02 | 160 |
133 | [커널 19차] 7주차 | kanlee | 2022.07.02 | 96 |
132 | [커널 19차] 6주차 | kanlee | 2022.07.02 | 42 |
131 | [커널 19차] 5주차 | kanlee | 2022.07.02 | 38 |
130 | [커널 19차] 4주차 | kanlee | 2022.07.02 | 106 |
129 | [커널 18차] 57주차 | kkr | 2022.06.25 | 129 |
.