您的位置:首頁 > 系統軟件

                                            一文搞懂 Linux 時鐘子系統

                                            發布時間:2022-04-13 22:57:11  來源:IT資訊網    采編:author  背景:

                                            不同的clock設置,需要從某個或某幾個時鐘源頭而來,最終開枝散葉,形成一顆時鐘樹??赏ㄟ^ cat /sys/kernel/debug/clk/clk_summary 查看這棵時鐘樹。

                                            內核中用 CCF 框架來管理 clock,如下所示,右邊是 clock 提供者,即 Clock Provider;中間是 CCF;左邊是設備驅動的 clock 使用者,即 Clock Consumer。

                                            Clock Provider

                                            根節點一般是 Oscillator(有源振蕩器)或者 Crystal(無源振蕩器)。

                                            中間節點有很多種,包括 PLL(鎖相環,用于提升頻率的),Divider(分頻器,用于降頻的),Mux(從多個clock path中選擇一個),Gate(用來控制ON/OFF的)。

                                            葉節點是使用 clock 做為輸入的、有具體功能的 HW block。

                                            根據 clock 的特點,clock framework 將 clock 分為 fixed rate、gate、devider、mux、fixed factor、composite 六類。

                                            數據結構

                                            上面六類本質上都屬于clock device,內核把這些 clock HW block 的特性抽取出來,用 struct clk_hw 來表示,具體如下:

                                            struct clk_hw { //指向CCF模塊中對應 clock device 實例 struct clk_core *core; //clk是訪問clk_core的實例。每當consumer通過clk_get對CCF中的clock device(也就是clk_core)發起訪問的時候都需要獲取一個句柄,也就是clk struct clk *clk; //clock provider driver初始化時的數據,數據被用來初始化clk_hw對應的clk_core數據結構。 const struct clk_init_data *init;};struct clk_init_data { //該clock設備的名字 const char *name; //clock provider driver進行具體的 HW 操作 const struct clk_ops *ops; //描述該clk_hw的拓撲結構 const char * const *parent_names; const struct clk_parent_data *parent_data; const struct clk_hw **parent_hws; u8 num_parents; unsigned long flags;};

                                            以固定頻率的振動器 fixed rate 為例,它的數據結構是:

                                            struct clk_fixed_rate { //下面是fixed rate這種clock device特有的成員 struct clk_hw hw; //基類 unsigned long fixed_rate; unsigned long fixed_accuracy; u8 flags;};

                                            其他的特定的clock device大概都是如此,這里就不贅述了。

                                            這里用一張圖描述這些數據結構之間的關系:

                                            注冊方式

                                            理解了數據結構,我們再看下每類 clock device 的注冊方式。

                                            1. fixed rate clock

                                            這一類clock具有固定的頻率,不能開關、不能調整頻率、不能選擇parent,是最簡單的一類clock??梢灾苯油ㄟ^ DTS 配置的方式支持。也可以通過接口,可以直接注冊 fixed rate clock,如下:

                                            CLK_OF_DECLARE(fixed_clk, "fixed-clock", of_fixed_clk_setup);struct clk *clk_register_fixed_rate(struct device *dev, const char *name, const char *parent_name, unsigned long flags, unsigned long fixed_rate);2. gate clock

                                            這一類clock只可開關(會提供.enable/.disable回調),可使用下面接口注冊:

                                            struct clk *clk_register_gate(struct device *dev, const char *name, const char *parent_name, unsigned long flags, void __iomem *reg, u8 bit_idx, u8 clk_gate_flags, spinlock_t *lock);3. divider clock

                                            這一類clock可以設置分頻值(因而會提供.recalc_rate/.set_rate/.round_rate回調),可通過下面兩個接口注冊:

                                            struct clk *clk_register_divider(struct device *dev, const char *name, const char *parent_name, unsigned long flags, void __iomem *reg, u8 shift, u8 width, u8 clk_divider_flags, spinlock_t *lock);struct clk *clk_register_divider_table(struct device *dev, const char *name, const char *parent_name, unsigned long flags, void __iomem *reg, u8 shift, u8 width, u8 clk_divider_flags, const struct clk_div_table *table, spinlock_t *lock);4. mux clock

                                            這一類clock可以選擇多個parent,因為會實現.get_parent/.set_parent/.recalc_rate回調,可通過下面兩個接口注冊:

                                            struct clk *clk_register_mux(struct device *dev, const char *name, const char **parent_names, u8 num_parents, unsigned long flags, void __iomem *reg, u8 shift, u8 width, u8 clk_mux_flags, spinlock_t *lock);struct clk *clk_register_mux_table(struct device *dev, const char *name, const char **parent_names, u8 num_parents, unsigned long flags, void __iomem *reg, u8 shift, u32 mask, u8 clk_mux_flags, u32 *table, spinlock_t *lock);5. fixed factor clock

                                            這一類clock具有固定的factor(即multiplier和divider),clock的頻率是由parent clock的頻率,乘以mul,除以div,多用于一些具有固定分頻系數的clock。由于parent clock的頻率可以改變,因而fix factor clock也可該改變頻率,因此也會提供.recalc_rate/.set_rate/.round_rate等回調??赏ㄟ^下面接口注冊:

                                            struct clk *clk_register_fixed_factor(struct device *dev, const char *name, const char *parent_name, unsigned long flags, unsigned int mult, unsigned int div);6. composite clock

                                            顧名思義,就是mux、divider、gate等clock的組合,可通過下面接口注冊:

                                            struct clk *clk_register_composite(struct device *dev, const char *name, const char **parent_names, int num_parents, struct clk_hw *mux_hw, const struct clk_ops *mux_ops, struct clk_hw *rate_hw, const struct clk_ops *rate_ops, struct clk_hw *gate_hw, const struct clk_ops *gate_ops, unsigned long flags);

                                            這些注冊函數最終都會通過函數 clk_register 注冊到 Common Clock Framework 中,返回為 struct clk 指針。如下所示:

                                            然后將返回的 struct clk 指針,保存在一個數組中,并調用 of_clk_add_provider 接口,告知 Common Clock Framework。

                                            Clock Consumer

                                            獲取 clock

                                            即通過 clock 名稱獲取 struct clk 指針的過程,由 clk_get、devm_clk_get、clk_get_sys、of_clk_get、of_clk_get_by_name、of_clk_get_from_provider 等接口負責實現,這里以 clk_get 為例,分析其實現過程:

                                            struct clk *clk_get(struct device *dev, const char *con_id){ const char *dev_id = dev ? dev_name(dev) : NULL; struct clk *clk; if (dev) { //通過掃描所有“clock-names”中的值,和傳入的name比較,如果相同,獲得它的index(即“clock-names”中的第幾個),調用of_clk_get,取得clock指針。 clk = __of_clk_get_by_name(dev->of_node, dev_id, con_id); if (!IS_ERR(clk) || PTR_ERR(clk) == -EPROBE_DEFER) return clk; } return clk_get_sys(dev_id, con_id);}struct clk *of_clk_get(struct device_node *np, int index){ struct of_phandle_args clkspec; struct clk *clk; int rc; if (index < 0) return ERR_PTR(-EINVAL); rc = of_parse_phandle_with_args(np, "clocks", "#clock-cells", index, &clkspec); if (rc) return ERR_PTR(rc); //獲取clock指針 clk = of_clk_get_from_provider(&clkspec); of_node_put(clkspec.np); return clk;}

                                            of_clk_get_from_provider 通過便利 of_clk_providers 鏈表,并調用每一個 provider 的 get 回調函數,獲取 clock 指針。如下:

                                            struct clk *of_clk_get_from_provider(struct of_phandle_args *clkspec){ struct of_clk_provider *provider; struct clk *clk = ERR_PTR(-ENOENT); /* Check if we have such a provider in our array */ mutex_lock(&of_clk_lock); list_for_each_entry(provider, &of_clk_providers, link) { if (provider->node == clkspec->np) clk = provider->get(clkspec, provider->data); if (!IS_ERR(clk)) break; } mutex_unlock(&of_clk_lock); return clk;}

                                            至此,Consumer 與 Provider 里講的 of_clk_add_provider 對應起來了。

                                            操作 clock//啟動clock前的準備工作/停止clock后的善后工作??赡軙?。int clk_prepare(struct clk *clk)void clk_unprepare(struct clk *clk)//啟動/停止clock。不會睡眠。static inline int clk_enable(struct clk *clk)static inline void clk_disable(struct clk *clk)//clock頻率的獲取和設置static inline unsigned long clk_get_rate(struct clk *clk)static inline int clk_set_rate(struct clk *clk, unsigned long rate)static inline long clk_round_rate(struct clk *clk, unsigned long rate)//獲取/選擇clock的parent clockstatic inline int clk_set_parent(struct clk *clk, struct clk *parent)static inline struct clk *clk_get_parent(struct clk *clk)//將clk_prepare和clk_enable組合起來,一起調用。將clk_disable和clk_unprepare組合起來,一起調用static inline int clk_prepare_enable(struct clk *clk)static inline void clk_disable_unprepare(struct clk *clk)

                                            總結

                                              聲明:本文僅為傳遞更多網絡信息,不代表IT資訊網觀點和意見,僅供參考了解,更不能作為投資使用依據。


                                            返回網站首頁 本文來源:IT資訊網

                                            本文評論
                                            微服務進展緩慢的5個難點
                                            筆者從2013年加入ThoughtWorks至今共4年時間。在這4年
                                            日期:01-22
                                            企業混合云的未來是什么?
                                            如今,許多組織仍難以將其整個工作負載移出辦公場所并遷
                                            日期:03-10
                                            未來邊緣智能的優勢及應用
                                            隨著收集數據并將其轉換到云端進行處理的物聯網設備數
                                            日期:03-24
                                            作業幫 Kubernetes 原生調度器優化實踐
                                            調度系統的本質是為計算服務/任務匹配合適的資源,使其
                                            日期:03-06
                                            正式版推送在即 外媒評Windows 10 RS5最佳新功能
                                            9月5日消息 近日,微軟已經正式公布了Windows 10 RS5更
                                            日期:10-02
                                            企業旅行社巨頭CWT或已支付450萬美元勒索軟件贖金
                                            CWT(Carlson Wagonlit Travel)是一家擁有全球客戶的企
                                            日期:02-14
                                            中小企業在云計算發展現狀及未來趨勢
                                            如果中小企業可以明白云、網、端三個詞的趨勢,了解云技
                                            日期:03-03
                                            那不是Bug,是新需求
                                            自從我干上軟件開發這一行,并且使用了Bug跟蹤系統,我們
                                            日期:03-12
                                            屬性動畫機制原理解析
                                            動畫的使用是 Android 開發中常用的知識,可是動畫的種
                                            日期:01-17
                                            零信任安全模型中的網絡和物聯網安全
                                            在網絡和物聯網安全方面,您永遠不會太小心。隨著越來越
                                            日期:01-25
                                            Three本月將為倫敦地鐵站提供免費Wi-Fi
                                            Wi-Fi信號已經通達倫敦地鐵,但要通過Wi-Fi上網,用戶需要
                                            日期:03-02
                                            以數據驅動創新 DaoCloud發布應用運營平臺DaoVoice
                                            3月24日,企業級容器云平臺和解決方案提供商 DaoCloud
                                            日期:02-17
                                             

                                            精品无码久久午夜福利