驅動開發硬核特訓 · Day 27(下篇):深入掌握 Common Clock Framework 架構與實戰開發

節。


在本篇內容中,我們將圍繞 Linux 內核中的時鐘子系統核心架構 —— Common Clock Framework(簡稱 CCF)展開深入講解,目標是幫助你全面理解其設計理念、主要數據結構、注冊流程、驅動實現方式,以及如何基于 NXP i.MX8MP 平臺進行完整的時鐘驅動開發。


一、Common Clock Framework 簡介

Common Clock Framework(CCF)是 Linux 內核自 v3.4 起引入的通用時鐘架構,用于統一管理 SoC 上所有的時鐘資源,解決平臺異構、驅動分裂、代碼冗余等問題。

CCF 的設計目標是:

  • 提供統一的時鐘抽象接口(如 clk_get() / clk_prepare() / clk_enable())。
  • 支持復雜的時鐘樹結構,包括分頻、門控、復用器等組件。
  • 支持時鐘源的動態切換與頻率動態調整(DFS)。
  • 解耦設備驅動與時鐘控制的實現。

二、CCF 的三大核心角色與架構總覽

在上一篇中我們已概述三個核心角色:

角色作用示例
時鐘提供者(Provider)注冊并實現時鐘控制邏輯,如 PLL、分頻器、門控器NXP CCM 時鐘控制器驅動
時鐘消費者(Consumer)使用時鐘接口獲取和啟用時鐘UART/I2C 等外設驅動
時鐘框架(Framework)統一管理所有時鐘,維護拓撲關系與接口drivers/clk/clk.c

架構示意圖:

+---------------------+      +-------------------+
| UART 驅動 (Consumer)|<---->|   CCF 框架層       |
+---------------------+      +-------------------+↑|+---------------------+| 時鐘控制器驅動       || (如 fsl-imx8mp-ccm)  |+---------------------+

在這里插入圖片描述

三、CCF 核心數據結構分析

1. struct clk_hw

該結構體表示一個底層時鐘硬件實體,由時鐘提供者實現:

struct clk_hw {struct clk_core *core;struct clk_init_data *init;// 可擴展的私有數據指針
};

2. struct clk_ops

用于定義操作時鐘的函數集,是最關鍵的回調接口:

struct clk_ops {int  (*enable)(struct clk_hw *hw);void (*disable)(struct clk_hw *hw);unsigned long (*recalc_rate)(struct clk_hw *hw, unsigned long parent_rate);long (*round_rate)(struct clk_hw *hw, unsigned long rate,unsigned long *parent_rate);int  (*set_rate)(struct clk_hw *hw, unsigned long rate,unsigned long parent_rate);...
};

3. struct clk_init_data

用于注冊時鐘時的初始化信息:

struct clk_init_data {const char *name;const struct clk_ops *ops;const char * const *parent_names;u8 num_parents;unsigned long flags;
};

四、時鐘提供者(Provider)注冊流程

Provider 通過 clk_register()devm_clk_hw_register()clk_hw 實例注冊給框架,框架內部建立 clk_core 對象并添加至全局時鐘樹。

示例流程:

  1. 定義 clk_ops 實現;
  2. 構造 clk_hw
  3. 填寫 clk_init_data
  4. 調用 devm_clk_hw_register() 完成注冊;
  5. 若是 platform 設備,通過 of_clk_add_hw_provider() 提供給設備樹接口。

五、實戰開發:NXP i.MX8MP 時鐘驅動解析

我們以 NXP i.MX8MP 的 UART2 根時鐘 IMX8MP_CLK_UART2_ROOT 為例,講解從時鐘控制器提供者,到 UART2 驅動消費者的完整鏈路。

1. 設備樹配置分析

uart2: serial@30890000 {compatible = "fsl,imx8mp-uart", "fsl,imx6q-uart";reg = <0x30890000 0x10000>;interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;clocks = <&clk IMX8MP_CLK_UART2_ROOT>,<&clk IMX8MP_CLK_UART2_ROOT>;clock-names = "ipg", "per";status = "disabled";
};

<&clk IMX8MP_CLK_UART2_ROOT> 表示設備節點引用了 ID 為 IMX8MP_CLK_UART2_ROOT 的時鐘,provider 必須實現它。

2. Provider 實現(drivers/clk/imx/clk-imx8mp.c)

static const struct imx8m_clk_root_clk uart2_root = {.id = IMX8MP_CLK_UART2_ROOT,.name = "uart2_root_clk",.parent_names = (const char *[]){ "uart2_div" },.num_parents = 1,.flags = CLK_SET_RATE_PARENT,
};

注冊流程:

hw = imx8m_clk_hw_register_composite(NULL, clk_root->name,clk_root->parent_names, clk_root->num_parents,mux_hw, &clk_mux_ops,rate_hw, &clk_divider_ops,gate_hw, &clk_gate_ops,clk_root->flags);

注: 每個 root clock 通常由一個復用器、一個分頻器和一個門控組成,符合 CCF 的復合時鐘模型。


六、時鐘消費者如何使用時鐘

驅動中使用以下接口獲取與控制時鐘:

struct clk *clk = devm_clk_get(dev, "ipg");
clk_prepare_enable(clk);
...
clk_disable_unprepare(clk);

內核根據 clock-names 字符串與設備樹中的 <&clk ID> 找到實際的 clk_core 實例,進一步調用對應 clk_ops 接口。


七、完整代碼實例:模擬一個外設時鐘 Provider

以下模擬一個名為 "demo-gate-clk" 的時鐘,基于 GPIO 控制實現一個簡單門控時鐘:

1. 示例平臺驅動結構:

static struct clk_hw *demo_clk_hw;
static struct clk_ops demo_clk_ops = {.enable = demo_clk_enable,.disable = demo_clk_disable,
};static int demo_clk_probe(struct platform_device *pdev)
{struct clk_init_data init;demo_clk_hw = devm_kzalloc(&pdev->dev, sizeof(*demo_clk_hw), GFP_KERNEL);init.name = "demo-gate-clk";init.ops = &demo_clk_ops;init.num_parents = 0;init.flags = 0;demo_clk_hw->init = &init;clk_hw_register(&pdev->dev, demo_clk_hw);of_clk_add_hw_provider(pdev->dev.of_node, of_clk_hw_simple_get, demo_clk_hw);return 0;
}

2. 在設備樹中描述該時鐘:

demo_clk: demo-clk {compatible = "vendor,demo-gate-clk";#clock-cells = <0>;
};

3. 在其他設備中消費該時鐘:

my_peripheral@12340000 {...clocks = <&demo_clk>;clock-names = "core";
};

八、Framework 的統一管理機制

Linux 內核 CCF 框架通過 clk_core 全局對象池,維持整個時鐘拓撲結構,并提供統一接口進行操作與調試。

核心文件位于 drivers/clk/clk.c,負責:

  • 初始化時鐘樹結構;
  • 實現 clk_get()clk_set_rate() 等函數;
  • 管理依賴關系(父子時鐘);
  • 調度跨時鐘域變更時的同步機制。

框架的調試接口如:

cat /sys/kernel/debug/clk/clk_summary

可查看當前系統所有時鐘狀態。


九、總結與實戰建議

  • Provider 注冊邏輯必須按 CCF 規則實現 clk_hwclk_ops,并注冊給框架;
  • Consumer 驅動應只依賴標準 clk_*() 接口,不直接操作硬件;
  • Framework 負責維護拓撲、管理父子關系、支持動態調頻調占;
  • 實戰中,先梳理平臺提供的 clock ID 定義(如 imx8mp-clock.h),再定位 clock controller 驅動;
  • 開發自定義外設或 FPGA 時鐘控制時,也可編寫 Provider 兼容設備樹接口。

十、每日提問與答案

問題 1:一個時鐘可以有多個父時鐘嗎?如何選擇?

回答:
可以。CCF 支持多父時鐘的復用器機制,注冊 clk_hw 時傳入多個 parent_names,并實現 set_parent()get_parent() 回調。使用者可調用 clk_set_parent() 選擇目標父時鐘。


問題 2:如何調試某個時鐘未啟用的問題?

回答:
可通過以下方式定位:

  • cat /sys/kernel/debug/clk/clk_summary 查看時鐘是否啟用;
  • 查看是否被 Consumer 使用并調用 clk_prepare_enable()
  • 檢查 Provider 的 clk_ops.enable() 是否被成功執行;
  • 驗證時鐘的 parent 是否啟用,是否存在 gating 問題。

以上即為 Day 27 下篇全部內容,完整講解了 CCF 架構設計與實際使用方式。
下一日我們將正式進入子系統與電源管理集成的驅動開發專題。

視頻教程請關注 B 站:“嵌入式 Jerry”

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/78516.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/78516.shtml
英文地址,請注明出處:http://en.pswp.cn/web/78516.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

數據庫基礎:數據庫類型與MySQL特點詳解

一、數據庫的主要類型 1. 關系型數據庫(RDBMS) 特點:基于關系模型,數據以表格形式存儲 代表產品:MySQL、Oracle、SQL Server、PostgreSQL 優勢:ACID事務支持、強一致性、成熟的SQL標準 適用場景:需要復雜查詢和事務支持的場景 2. 非關系型數據庫(NoSQL) 文檔型數據庫:Mo…

49認知干貨:產品的生命周期及類型匯總

49章:產品的生命周期與類型劃分 宇宙是運動的而非靜止的,任何事物亦是如此。只要是存在的事物,便必然存在周期性變化,就像四季更替中的冬日枯樹、春日新芽、夏日繁茂與秋日凋零。 這也意味著:事物的發展,離不開周期的更迭與演化,死亡并非終點,而是一種新的循環轉變。 …

【2025最新】為什么用ElasticSearch?和傳統數據庫MySQL與什么區別?

Elasticsearch 深度解析&#xff1a;從原理到實踐 一、為什么選擇 Elasticsearch&#xff1f; 數據模型 Elasticsearch 是基于文檔的搜索引擎&#xff0c;它使用 JSON 文檔來存儲數據。在 Elasticsearch 中&#xff0c;相關的數據通常存儲在同一個文檔中&#xff0c;而不是分散…

Docker安裝Gitblit(圖文教程)

本章教程,使用Docker安裝部署Gitblit。 一、Gitblit簡介 Gitblit 是一個基于 Java 的 Git 倉庫管理工具,主要用于在局域網或小型團隊環境中搭建私有 Git 服務器。它提供了一個簡單易用的 Web 界面,用于瀏覽代碼、管理倉庫和用戶權限等。 二、拉取鏡像 sudo docker pull git…

nDCG(歸一化折損累計增益) 是衡量排序質量的指標,常用于搜索引擎或推薦系統

nDCG&#xff08;歸一化折損累計增益&#xff09; 是衡量排序質量的指標&#xff0c;常用于搜索引擎或推薦系統。核心思想是&#xff1a;排名越靠前的高質量結果&#xff0c;對整體評分的貢獻越大&#xff0c;但后續結果的貢獻會逐漸“打折”。最終通過對比實際排序與理想排序的…

《從線性到二維:CSS Grid與Flex的布局范式革命與差異解析》

在前端開發的廣袤宇宙中&#xff0c;CSS布局技術宛如閃耀的星辰&#xff0c;不斷革新與演進&#xff0c;為構建絢麗多彩的網頁世界提供了堅實的支撐。其中&#xff0c;CSS Grid布局與Flex布局作為兩顆璀璨的明星&#xff0c;以其獨特的魅力和強大的功能&#xff0c;深受開發者們…

2025年01月03日美蜥(杭州普瑞兼職)一面

目錄 vue2 vue3 的區別react 性能優化react 組件傳值v-for 和 v-if 的優先級react 中多個接口請求的數據&#xff0c;需要渲染到一個列表上怎么處理百萬條數據怎么渲染vue2、vue3 的響應式原理微前端了解嗎git 版本控制git mearge 和 git rebase 的區別垂直水平居中react 中實…

【聚類分析】基于copula的風光聯合場景生成與縮減

目錄 1 主要內容 風光出力場景生成方法 2 部分程序 3 程序結果 4 下載鏈接 1 主要內容 該程序方法復現《融合風光出力場景生成的多能互補微網系統優化配置》風光出力場景生成部分&#xff0c;目前大多數研究的是不計風光出力之間的相關性影響&#xff0c;但是地理位置相近…

LeetCode 1128 等價多米諾骨牌對的數量 題解

今天的每日一題&#xff0c;我的思路還是硬做&#xff0c;不如評論區通過狀壓寫的簡單&#xff0c;但是答題思路加算法實現是沒有問題的&#xff0c;且時間復雜度也是可以通過的&#xff0c;畢竟全是o(n) 那么我就來說一下我的思路&#xff0c;根據dominoes[i] [a, b] 與 domi…

技術部測試規范

簡短測試流程&#xff1a; 開發完成 -> 本地自測 -> 測試環境自測 -> 通知測試同事復測 -> 確認無誤后上生產 -> 生產環境自測 -> 再次通知測試同事復測 -> 提交產品驗收。 當然可以&#xff01;以下是進一步優化后的測試流程規范&#xff0c;特別強調了開…

算法每日一題 | 入門-順序結構-大象喝水

大象喝水 題目描述 一只大象口渴了&#xff0c;要喝 20 升水才能解渴&#xff0c;但現在只有一個深 h 厘米&#xff0c;底面半徑為 r 厘米的小圓桶 &#xff08;h 和 r 都是整數&#xff09;。問大象至少要喝多少桶水才會解渴。 這里我們近似地取圓周率 π 3.14 \pi3.14 π…

Qt中實現工廠模式

在Qt中實現工廠模式可以通過多種方式&#xff0c;具體選擇取決于需求和場景。以下是幾種常見的實現方法&#xff1a; 1. 簡單工廠模式通過一個工廠類根據參數創建不同對象。cppclass Shape {public: virtual void draw() 0; virtual ~Shape() default;};class Circle : publ…

【前端】ES6一本通_劃重點_補充面試題

近兩天更新完基本內容&#xff0c;后續長期更新&#xff0c;建議關注收藏點贊。 ES6&#xff08;ECMAScript 2015&#xff09;是現代 JavaScript 的基礎&#xff0c;在前端面試中非常常見。 本文已匯總的本站筆記 ES6最重要10特性 對象新增 數組新增 異步、生成器 Promise 模塊…

初識 iOS 開發中的證書固定

引言 在移動應用安全領域&#xff0c;HTTPS/TLS 是數據傳輸的第一道防線&#xff0c;但僅依賴系統默認的證書驗證仍有被中間人&#xff08;MITM&#xff09;攻擊的風險。Certificate Pinning&#xff08;證書固定&#xff09;通過將客戶端信任“釘”在指定的服務器證書或公鑰上…

單片機的各個種類及其詳細介紹

一、按架構分類的深度解析 1. ARM Cortex-M系列 核心優勢&#xff1a; 統一架構&#xff1a;ARM生態完善&#xff0c;工具鏈&#xff08;Keil、IAR、GCC&#xff09;通用。 性能分層&#xff1a;M0&#xff08;低功耗&#xff09;、M3&#xff08;平衡&#xff09;、M4/M7&am…

5.7/Q1,GBD數據庫最新文章解讀

文章題目&#xff1a;Global, regional, and national burden and trends of rheumatoid arthritis among the elderly population: an analysis based on the 2021 Global Burden of Disease study DOI&#xff1a;10.3389/fimmu.2025.1547763 中文標題&#xff1a;全球、區域…

從微服務到AI服務:Nacos 3.0如何重構下一代動態治理體系?

在現代微服務架構的浪潮中&#xff0c;Nacos早已成為開發者手中的“瑞士軍刀”。作為阿里巴巴開源的核心中間件&#xff0c;它通過動態服務發現、統一配置管理和服務治理能力&#xff0c;為云原生應用提供了堅實的基石。從初創公司到全球500強企業&#xff0c;Nacos憑借其開箱即…

Unity與Unreal Engine(UE)的深度解析及高級用法

以下是Unity與Unreal Engine(UE)的深度解析及高級用法對比,結合技術特性、行業應用與未來發展進行綜合闡述: 一、核心差異與適用場景對比 1. 技術架構與編程模式 Unity 語言與腳本:主要使用C#,語法簡潔且易于學習,適合快速原型開發和中小型項目。支持可視化腳本工具(如…

李沐動手深度學習(pycharm中運行筆記)——05.線性代數

05.線性代數&#xff08;與課程對應&#xff09; 1、導入torch import torch2、 標量由只有一個元素的張量表示 x torch.tensor([3.0]) y torch.tensor([2.0]) print("x y:", x y, "\nx * y:", x * y, "\nx / y:", x / y, "\nx ** y…

Python3與Dubbo3.1通訊解決方案(dubbo-python)

【文章非VIP可讀&#xff0c;如果發現閱讀限制為系統自動修改閱讀權限&#xff0c;請留言我改回】 概述 最近AI項目需要java與python通訊&#xff0c;兩邊都是比較新的版本。因此需要雙方進行通訊&#xff0c;在這里記錄一下所采用的方案和關鍵點。 JAVA調用Python python通…