CLKO1 可以選擇 GPIO0 做 clk output
CLKO2 可以選擇 GPIO3 做 clk output
CLKO1.2 的控制 register 在 CCM_CCOSR (offset 0x60)
對照 kernel source : clk-imx6q.c
在 source code 李,叫 cko1, cko2
clk[cko1] = imx_clk_gate("cko1", "cko1_podf", base + 0x60, 7);
clk[cko2] = imx_clk_gate("cko2", "cko2_podf", base + 0x60, 24);
....
clk[cko1_podf] = imx_clk_divider("cko1_podf", "cko1_sel", base + 0x60, 4, 3);
clk[cko2_podf] = imx_clk_divider("cko2_podf", "cko2_sel", base + 0x60, 21, 3);
....
clk[cko1_sel] = imx_clk_mux("cko1_sel", base + 0x60, 0, 4, cko1_sels, ARRAY_SIZE(cko1_sels));
clk[cko2_sel] = imx_clk_mux("cko2_sel", base + 0x60, 16, 5, cko2_sels, ARRAY_SIZE(cko2_sels));
....
clk 是 struct clk
clk 軟體模型,依照一般 clk 的設置,叫下面的名子。:
- clk source : parent, mux (imx_clk_mux)
- divider : divider (imx_clk_divider)
- enable/disable : gate (imx_clk_gate)
拿 gate 來看,對照 datasheet, CCM_CCOSR:
- bit 24: CLKO2_EN : enable/disable CLKO2
- bit 21-23 : CLKO2_DIV : divider by 1,2,3,4...8
- bit 16-20 : CLKO2_SEL : clko2 的 clk src
- bit 7 : CLKO1_EN
- bit 4-6 : CLKO1_DIV
- bit 0-3 : CLKO1_SEL
然後,因為這三個類型的操作不太相同,所以要為每個類型寫一個 operatio function.
各是:clk-gate2.c, clk-fixup-div.c, clk-fixup-mix.c
以 gate 來說。
implement imx_clk_gate 的code 在 clk-gate2.c
static struct clk_ops clk_gate2_ops = {
.enable = clk_gate2_enable,
.disable = clk_gate2_disable,
.is_enabled = clk_gate2_is_enabled,
};
主要就是要實做這三個 gate 的 function.enable/disable 最後 就是...
static void clk_gate2_do_hardware(struct clk_gate2 *gate, bool enable)
{
u32 reg;
reg = readl(gate->reg);
if (enable)
reg |= CCM_CCGR_FULL_ENABLE << gate->bit_idx;
else
reg &= ~(CCM_CCGR_FULL_ENABLE << gate->bit_idx);
writel(reg, gate->reg);
}
統一的 clk interface 在 driver/clk/clk.c
呼叫 clk_enable( ) 就會:
static int __clk_enable(struct clk *clk)
{
int ret = 0;
if (!clk)
return 0;
if (WARN_ON(clk->prepare_count == 0))
return -ESHUTDOWN;
if (clk->enable_count == 0) {
ret = __clk_enable(clk->parent);
if (ret)
return ret;
if (clk->ops->enable) {
ret = clk->ops->enable(clk->hw);
if (ret) {
__clk_disable(clk->parent);
return ret;
}
}
}
clk->enable_count++;
return 0;
}
-- 另外,一般用 clk_prepare_enable( )
所以,一定要 call 過 enable( ), 那個 clock 才會動。
沒有留言:
張貼留言