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 才會動。
沒有留言:
張貼留言