裡面除了 struck clk 外,還定義了:
DEFINE_CLK DEFINE_CLK_FIXED_RATE DEFINE_CLK_GATE DEFINE_CLK_DIVIDER DEFINE_CLK_DIVIDER_TABLE DEFINE_CLK_MUX DEFINE_CLK_FIXED_FACTOR但是這些imx 都沒用...
是在arch/arm/mach-imx/clk-imx6q.c 中宣告,生成。
CLK_OF_DECLARE(imx6q, "fsl,imx6q-ccm", imx6q_clocks_init);device tree 宣告在: imx6qdl.dtsi:
clks: ccm@020c4000 { compatible = "fsl,imx6q-ccm"; reg = <0x020c4000 0x4000>; interrupts = <0 87 0x04 0 88 0x04>; #clock-cells = <1>; };
在 Documentation/devicetree/bindings/clock/imx6q-clock.txt 有清楚的說明:
每個使用clk 的裝置(consumer) 都要在 device tree 中指名使用到的 clk id
imx bsp 把所有的 clk 排列在一起,並且給每個clk 一個index
Clock ID --------------------------- dummy 0 ckil 1 ckih 2 osc 3 pll2_pfd0_352m 4 pll2_pfd1_594m 5 pll2_pfd2_396m 6 pll3_pfd0_720m 7 pll3_pfd1_540m 8 pll3_pfd2_508m 9 pll3_pfd3_454m 10 pll2_198m 11 pll3_120m 12 pll3_80m 13 pll3_60m 14 twd 15 step 16 pll1_sw 17 periph_pre 18 periph2_pre 19 periph_clk2_sel 20 periph2_clk2_sel 21 axi_sel 22 esai_sel 23 spdif1_sel 24 spdif_sel 25 ...
這個表其實宣告在 clk-imx6q.c 的 enum mx6q_clks {}
系統clock 的 device node:
Examples: clks: ccm@020c4000 { compatible = "fsl,imx6q-ccm"; reg = <0x020c4000 0x4000>; interrupts = <0 87 0x04 0 88 0x04>; #clock-cells = <1>; };
以 serial port (UART) 為例,他使用兩種clk, ipg, serial, 所以 device node 是:
uart1: serial@02020000 { compatible = "fsl,imx6q-uart", "fsl,imx21-uart"; reg = <0x02020000 0x4000>; interrupts = <0 26 0x04>; clocks = <&clks 160>, <&clks 161>; clock-names = "ipg", "per"; status = "disabled"; };idex 分別是 160, 161
clock 的 hierachy 是寫在 clk-imx6q.c:
imx6q_clocks_init( ):
約略是由上而下...
clk[dummy] = imx_clk_fixed("dummy", 0); clk[ckil] = imx_obtain_fixed_clock("ckil", 0); clk[ckih] = imx_obtain_fixed_clock("ckih1", 0); clk[osc] = imx_obtain_fixed_clock("osc", 0); /* Clock source from external clock via ANACLK1/2 PADs */ clk[anaclk1] = imx_obtain_fixed_clock("anaclk1", 0); clk[anaclk2] = imx_obtain_fixed_clock("anaclk2", 0);ckil : external low freq
ckih : external high freq clock and internal oscillator
osc : the 24MHz
anaclk1, anaclk2 : another external osc in
這幾個 最源頭的 clk 都定義在 dts 中。
最後系統的 clk hierachy, 在 debugfs 中可以看到: wondboard:
root@wandboard:/sys/kernel/debug/clk # busybox find . -name 'esai*' ./osc/pll2_bus/pll2_pfd2_396m/periph_pre/periph/ahb/esai_ipg ./osc/pll2_bus/pll2_pfd2_396m/periph_pre/periph/ahb/esai_mem ./osc/pll4_sel/pll4_audio/pll4_post_div/pll4_audio_div/esai_sel ./osc/pll4_sel/pll4_audio/pll4_post_div/pll4_audio_div/esai_sel/esai_pred ./osc/pll4_sel/pll4_audio/pll4_post_div/pll4_audio_div/esai_sel/esai_pred/esai_podf ./osc/pll4_sel/pll4_audio/pll4_post_div/pll4_audio_div/esai_sel/esai_pred/esai_podf/esai_extalsabreauto:
root@sabreauto_6q:/sys/kernel/debug/clk # busybox find . -name 'esai*' ./osc/pll2_bus/pll2_pfd2_396m/periph_pre/periph/ahb/esai_ipg ./osc/pll2_bus/pll2_pfd2_396m/periph_pre/periph/ahb/esai_mem ./anaclk2/lvds2_in/pll4_sel/pll4_audio/pll4_post_div/pll4_audio_div/esai_sel ./anaclk2/lvds2_in/pll4_sel/pll4_audio/pll4_post_div/pll4_audio_div/esai_sel/esai_pred ./anaclk2/lvds2_in/pll4_sel/pll4_audio/pll4_post_div/pll4_audio_div/esai_sel/esai_pred/esai_podf ./anaclk2/lvds2_in/pll4_sel/pll4_audio/pll4_post_div/pll4_audio_div/esai_sel/esai_pred/esai_podf/esai_extal因為 mach-imx6q.c 的 ..
static void __init imx6q_audio_lvds2_init(void) { struct clk *pll4_sel, *lvds2_in, *pll4_audio_div, *esai_extal; printk("%s\n",__func__); pll4_audio_div = clk_get_sys(NULL, "pll4_audio_div"); pll4_sel = clk_get_sys(NULL, "pll4_sel"); lvds2_in = clk_get_sys(NULL, "lvds2_in"); esai_extal = clk_get_sys(NULL, "esai_extal"); if (IS_ERR(pll4_audio_div) || IS_ERR(pll4_sel) || IS_ERR(lvds2_in) || IS_ERR(esai_extal)) return; if (clk_get_rate(lvds2_in) != ESAI_AUDIO_MCLK) return; clk_set_parent(pll4_sel, lvds2_in); clk_set_rate(pll4_audio_div, 786432000); clk_set_rate(esai_extal, ESAI_AUDIO_MCLK); }把 pll4_sel 的 parent 改到 lvds2_in
pll4_sel 的 parent 可以是:
{ "osc", "lvds1_in", "lvds2_in", "dummy", }
沒有留言:
張貼留言