時鐘相關基本知識可先參考這篇http://www.linuxidc.com/Linux/2012-02/54968.htm
下面直接從總線時鐘初始化函數開始分析:
- void __init s3c244x_init_clocks(int xtal)
- {
- /* initialise the clocks here, to allow other things like the
- * console to use them, and to add new ones after the initialisation
- */
-
- s3c24xx_register_baseclocks(xtal);
- s3c244x_setup_clocks();
- s3c2410_baseclk_add();
- }
s3c24xx_init_clocks主要實現兩個功能:
1.初始化s3c2440的總線時鐘。通過s3c24xx_register_baseclocks(xtal)和s3c244x_setup_clocks實現
2.想系統注冊外設時鐘。通過s3c2410_baseclk_add()實現
首先分析初始化系統時鐘
- int __init s3c24xx_register_baseclocks(unsigned long xtal)
- {
- printk(KERN_INFO "S3C24XX Clocks, Copyright 2004 Simtec Electronics\n");
-
- clk_xtal.rate = xtal;
-
- /* register our clocks */
-
- if (s3c24xx_register_clock(&clk_xtal) < 0)
- printk(KERN_ERR "failed to register master xtal\n");
-
- if (s3c24xx_register_clock(&clk_mpll) < 0)
- printk(KERN_ERR "failed to register mpll clock\n");
-
- if (s3c24xx_register_clock(&clk_upll) < 0)
- printk(KERN_ERR "failed to register upll clock\n");
-
- if (s3c24xx_register_clock(&clk_f) < 0)
- printk(KERN_ERR "failed to register cpu fclk\n");
-
- if (s3c24xx_register_clock(&clk_h) < 0)
- printk(KERN_ERR "failed to register cpu hclk\n");
-
- if (s3c24xx_register_clock(&clk_p) < 0)
- printk(KERN_ERR "failed to register cpu pclk\n");
-
- return 0;
- }
依次向注冊clk_xtal、clk_mpll、clk_upll... ...clk_p等時鐘,clk_p等的定義如下:
- struct clk clk_p = {
- .name = "pclk",
- .id = -1,
- .rate = 0,
- .parent = NULL,
- .ctrlbit = 0,
- .ops = &clk_ops_def_setrate,
- };
注冊成功後然後通過s3c244x_setup_clocks->s3c24xx_setup_clocks(fclk, hclk, pclk)來初始化前面注冊的各個時鐘。
- void __init_or_cpufreq s3c24xx_setup_clocks(unsigned long fclk,
- unsigned long hclk,
- unsigned long pclk)
- {
- clk_upll.rate = s3c24xx_get_pll(__raw_readl(S3C2410_UPLLCON),
- clk_xtal.rate);
-
- clk_mpll.rate = fclk;
- clk_h.rate = hclk;
- clk_p.rate = pclk;
- clk_f.rate = fclk;
- }