Linux clock子系统是什么

描述

clock子系统

Linux的时钟子系统由CCF(common clock framework)框架管理, CCF向上给用户提供了通用的时钟接口,向下给驱动开发者提供硬件操作的接口 。各结构体关系如下:

接口

CCF框架比较简单,只有这几个结构体。CCF框架分为了consumer、ccf和provider三部分。

consumer

时钟的使用者,clock子系统向consumer的提供通用的时钟API接口,使其可以屏蔽底层硬件差异。提供给consumer操作的API如下:

struct clk *clk_get(struct device *dev, const char *id);
struct clk *devm_clk_get(struct device *dev, const char *id);
int clk_enable(struct clk *clk);//使能时钟,不会睡眠
void clk_disable(struct clk *clk);//使能时钟,不会睡眠
unsigned long clk_get_rate(struct clk *clk);
void clk_put(struct clk *clk);
long clk_round_rate(struct clk *clk, unsigned long rate);
int clk_set_rate(struct clk *clk, unsigned long rate);
int clk_set_parent(struct clk *clk, struct clk *parent);
struct clk *clk_get_parent(struct clk *clk);
int clk_prepare(struct clk *clk);
void clk_unprepare(struct clk *clk);
int clk_prepare_enable(struct clk *clk) //使能时钟,可能会睡眠
void clk_disable_unprepare(struct clk *clk) //禁止时钟,可能会睡眠
unsigned long clk_get_rate(struct clk *clk) //获取时钟频率

consumer在使用这些API时,必须先调用devm_clk_get()clk_get()获取一个struct clk *指针句柄,后续都通过传入该句柄来操作,struct clk相当于实例化一个时钟。

ccf

clock子系统的核心,用一个struct clk_core结构体表示,每个注册设备都对应一个struct clk_core

provider(时钟的提供者)

struct clk_hw:表示一个具体的硬件时钟。

struct clk_init_data:struct clk_hw结构体成员,用于表示该时钟下的初始化数据,如时钟名字name、操作函数ops等。

// include/linux/clk-provider.h
struct clk_hw{
 struct clk_core *core;
 struct clk *clk;
 const struct clk_init_data *init;
}

struct clk_init_data{
 const char *name;     //时钟名字
 const struct clk_ops *ops;   //时钟硬件操作函数集合
 const char *const *parent_names; //父时钟名字
 const struct clk_parent_data *parent_data;
 const struct clk_hw **parent_hws;
 u8 num_parents;
 unsigned long flags;
}

struct clk_ops:时钟硬件操作的函数集合,定义了操作硬件的回调函数,consumer在调用clk_set_rate()等API时会调用到struct clk_ops具体指向的函数,这个需要芯片厂商开发clock驱动时去实现。

//include/linux/clk-provider.h

struct clk_ops {
 int  (*prepare)(struct clk_hw *hw);
 void  (*unprepare)(struct clk_hw *hw);
 int  (*is_prepared)(struct clk_hw *hw);
 void  (*unprepare_unused)(struct clk_hw *hw);
 int  (*enable)(struct clk_hw *hw);
 void  (*disable)(struct clk_hw *hw);
 int  (*is_enabled)(struct clk_hw *hw);
 void  (*disable_unused)(struct clk_hw *hw);
 int  (*save_context)(struct clk_hw *hw);
 void  (*restore_context)(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  (*determine_rate)(struct clk_hw *hw,
       struct clk_rate_request *req);
 int  (*set_parent)(struct clk_hw *hw, u8 index);
 u8  (*get_parent)(struct clk_hw *hw);
 int  (*set_rate)(struct clk_hw *hw, unsigned long rate,
        unsigned long parent_rate);
 int  (*set_rate_and_parent)(struct clk_hw *hw,
        unsigned long rate,
        unsigned long parent_rate, u8 index);
 unsigned long (*recalc_accuracy)(struct clk_hw *hw,
        unsigned long parent_accuracy);
 int  (*get_phase)(struct clk_hw *hw);
 int  (*set_phase)(struct clk_hw *hw, int degrees);
 int  (*get_duty_cycle)(struct clk_hw *hw,
       struct clk_duty *duty);
 int  (*set_duty_cycle)(struct clk_hw *hw,
       struct clk_duty *duty);
 int  (*init)(struct clk_hw *hw);
 void  (*terminate)(struct clk_hw *hw);
 void  (*debug_init)(struct clk_hw *hw, struct dentry *dentry);
};

struct clk_ops中每个函数功能在include/linux/clk-provider.h都有具体的说明,在开发clock驱动时,这些函数并不需要全部实现。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分