設備樹中時鍾


時鍾框圖

 

先來看看S3C2440時鍾的硬件框圖:

 

 

將該圖簡化如下:

 

 我們只想作為消費者怎么去使用這些時鍾,並不關心“提供者”內部的層級結構,只要知道“直接提供者”,也不關系“直接提供者”的實現,我們只需要發出請求就可以了。

 

晶振設備樹描述

我們看看在2440的設備樹里怎么描述這提供者和消費者。先來看看晶振:

    xti: xti_clock {
        compatible = "fixed-clock";
        clock-frequency = <12000000>;
        clock-output-names = "xti";
        #clock-cells = <0>;
    };

根據compatible可以找到對應的驅動,驅動程序將晶振的頻率記錄下來,以后作為計算的基准。

然后再是PLL的設備節點:

    clocks: clock-controller@4c000000 {
        compatible = "samsung,s3c2440-clock";
        reg = <0x4c000000 0x20>;
        #clock-cells = <1>;
    };

設備節點本身非常簡單,復雜的是它對應的驅動程序。在驅動程序里面,肯定會根據reg獲得寄存器的地址,然后設置各種內容。


大部分的芯片為了省電,它的外部模塊時鍾平時都是關閉的,只有在使用某個模塊時,才設置相應的寄存器開啟對應的時鍾。


這些使用者各有不同,要怎么描述這些使用者呢?

我們可以為它們配上一個ID。在設備樹中的#clock-cells = <1>;表示 用多少個u32位來描述消費者。在本例中使用一個u32來描述。


這些ID值由誰提供的?

是由驅動程序提供的,該節點會對應一個驅動程序,驅動程序給硬件(消費者)都分配了一個ID,所以說復雜的操作都留給驅動程序來做。

LCD時鍾設備樹描述

消費者想使用時鍾時,首先要找到時鍾的直接提供者,向它發出申請。以LCD為例:

    fb0: fb@4d000000{
        compatible = "jz2440,lcd";
        reg = <0x4D000000 0x60>;
        interrupts = <0 0 16 3>;
        clocks = <&clocks HCLK_LCD>;
        clock-names = "lcd";
        ……
    }

clock屬性里,首先要確定向誰發出時鍾申請,這里是向clocks發出申請,然后確定想要時鍾提供者提供哪一路時鍾,這里是HCLK_LCD,在驅動程序里定義了該宏,每種宏對應了一個時鍾ID。

定義如下:

……
/* hclk-gates */
#define HCLK_LCD        32
#define HCLK_USBH        33
#define HCLK_USBD        34
#define HCLK_NAND        35
#define HCLK_CAM        36
……

因此,我們只需要在設備節點定義clocks這個屬性,這個屬性確定時鍾提供者,然后確定時鍾ID,也就是向時鍾提供者申請哪一路時鍾。

對應的內核文檔可以參考這兩個文件:

Documentation/devicetree/bindings/clock/clock-bindings.txt
Documentation/devicetree/bindings/clock/samsung,s3c2410-clock.txt

那么我這個設備驅動程序,怎么去使用這些時鍾呢? 以前的驅動程序:clk_get(NULL, "name"); clk_prepare_enable(clk); 現在的驅動程序:of_clk_get(node, 0); clk_prepare_enable(clk);

總結

a. 設備樹中定義了各種時鍾, 在文檔中稱之為"Clock providers", 比如:

    clocks: clock-controller@4c000000 {
        compatible = "samsung,s3c2440-clock";
        reg = <0x4c000000 0x20>;
        #clock-cells = <1>;      // 想使用這個clocks時要提供1個u32來指定它, 比如選擇這個clocks中發出的LCD時鍾、PWM時鍾
    };

b. 設備需要時鍾時, 它是"Clock consumers", 它描述了使用哪一個"Clock providers"中的哪一個時鍾(id), 比如:

    fb0: fb@4d000000{
        compatible = "jz2440,lcd";
        reg = <0x4D000000 0x60>;
        interrupts = <0 0 16 3>;
        clocks = <&clocks HCLK_LCD>;  // 使用clocks即clock-controller@4c000000中的HCLK_LCD        
    };

c. 驅動中獲得/使能時鍾:

    // 確定時鍾個數
    int nr_pclks = of_count_phandle_with_args(dev->of_node, "clocks",
                        "#clock-cells");
    // 獲得時鍾
    for (i = 0; i < nr_pclks; i++) {
        struct clk *clk = of_clk_get(dev->of_node, i);
    }

    // 使能時鍾
    clk_prepare_enable(clk);

    // 禁止時鍾
    clk_disable_unprepare(clk);

 

 

 

第六課:在LCD驅動中使用設備樹


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM