Windows XP Windows 7 Windows 2003 Windows Vista Windows 綜合教學 Linux 系統教學
Windows 10 Windows 8 Windows 2008 Windows NT Windows Server 電腦軟體教學
您现在的位置: Windows教程網 >> Windows教程 >  >> Linux 系統教學 >> Linux 教學

Linux 時鐘框架核心結構與操作指南

編輯:Linux 教學

Linux 核心的 Common Clock Framework (CCF) 為 SoC 複雜的時鐘樹提供統一抽象。本文解析核心資料結構 struct clk、struct clk_ops 及 Samsung 專用的 clksrc_clk,並示範如何取得外部晶振頻率。

核心操作介面:struct clk_ops

所有具體時鐘驅動需實作此介面,提供設定/讀取頻率、父時鐘切換等操作:

struct clk_ops {
    int (*set_rate)(struct clk *c, unsigned long rate);
    unsigned long (*get_rate)(struct clk *c);
    unsigned long (*round_rate)(struct clk *c, unsigned long rate);
    int (*set_parent)(struct clk *c, struct clk *parent);
};

基礎時鐘物件:struct clk

每個時鐘節點在核心中對應一個 struct clk 實例:

struct clk {
    struct list_head list;        // 掛載至全域時鐘鏈表
    struct module *owner;         // 模組擁有者
    struct clk *parent;           // 父時鐘指標
    const char *name;             // 時鐘名稱(如 "mout_apll")
    int id;                       // 識別碼
    int usage;                    // 參考計數
    unsigned long rate;           // 當前頻率
    unsigned long ctrlbit;        // 控制暫存器位元
    struct clk_ops *ops;          // 操作函數集
    int (*enable)(struct clk *, int enable); // 啟用/停用回調
};

Samsung 多工時鐘來源:clksrc_clk

新款 SoC 採用 Mux + Divider 架構,clksrc_clk 封裝此邏輯:

struct clksrc_sources {
    unsigned int nr_sources;
    struct clk **sources;         // 可能的父時鐘陣列
};

struct clksrc_reg {
    void __iomem *reg;            // 暫存器虛擬位址
    unsigned short shift;         // 位元偏移
    unsigned short size;          // 位元寬度
};

struct clksrc_clk {
    struct clk clk;               // 繼承基礎結構
    struct clksrc_sources *sources; // 來源清單
    struct clksrc_reg reg_src;    // 來源選擇暫存器
    struct clksrc_reg reg_div;    // 分頻器暫存器
};

實際案例:APLL/MPLL/EPLL 輸出多工器

以 clk_mout_apll 為例,其來源為 clk_src_apll(外部晶振或 APLL 輸出):

static struct clksrc_clk clk_mout_apll = {
    .clk = { .name = "mout_apll", .id = -1 },
    .sources = &clk_src_apll,
    .reg_src = { .reg = S5P_CLK_SRC0, .shift = 0, .size = 1 },
};

static struct clk *clk_src_apll_list[] = {
    [0] = &clk_fin_apll,   // 外部晶振
    [1] = &clk_fout_apll,  // APLL 輸出
};
struct clksrc_sources clk_src_apll = {
    .sources = clk_src_apll_list,
    .nr_sources = ARRAY_SIZE(clk_src_apll_list),
};

// 統一定義外部晶振
#define clk_fin_apll clk_ext_xtal_mux
struct clk clk_ext_xtal_mux = { .name = "ext_xtal", .id = -1 };

應用層取得晶振頻率

驅動程式可透過標準 API 取得外部晶振頻率:

struct clk *xtal_clk = clk_get(NULL, "ext_xtal");
unsigned long xtal = clk_get_rate(xtal_clk);

關鍵概念總結

  • 時鐘樹:以 parent 指標串聯,根節點通常為固定頻率晶振或 PLL。
  • 參考計數:clk_prepare_enable()/clk_disable_unprepare() 管理 usage,歸零時硬體才真正關閉。
  • 分層抽象:clksrc_clk 封裝 Mux/Div 硬體細節,驅動只需實作 clk_ops 即可複用核心邏輯。

掌握此架構,可高效開發新 SoC 時鐘驅動,並利用 clkdev 查找機制讓裝置驅動無縫取得所需時鐘。

Copyright © Windows教程網 All Rights Reserved