clk子系统 - 驱动框架
clk子系统负责为整个系统硬件提供时钟信号,这个要和linux的时钟系统区别开来;现在的ASoC上包含许多clk模块,比如晶振,pll,divider等,那么clk子系统就把这些模块抽象出来,并形成一个驱动框架,这样对于其他驱动开发人员来说,只需要调用通用的接口就能操作各自设备的clk,没必要从上到下重新配置clk1.驱动框架clk驱动框架如上图,API层是提供操作clk的通用...
clk子系统负责为整个系统硬件提供时钟信号,这个要和linux的时钟系统区别开来;现在的ASoC上包含许多clk模块,比如晶振,pll,divider等,那么clk子系统就把这些模块抽象出来,并形成一个驱动框架,这样对于其他驱动开发人员来说,只需要调用通用的接口就能操作各自设备的clk,没必要从上到下重新配置clk
1.驱动框架
clk驱动框架如上图,API层是提供操作clk的通用接口,CORE层是抽象各个clk设备为一个对象加入到框架中,HARDWARE层主要是为不同的clk设备生成一个对象,最后会加入到一个clk链表:
static HLIST_HEAD(clk_root_list);
static HLIST_HEAD(clk_orphan_list);
如果你是个根设备那个就加入clk_root_list,其他的clk设备加入到clk_orphan_list,它们的关系如下图:
2.相关结构体及关系
2.1 struct clk
struct clk {
const char *name;
const struct clk_ops *ops;
struct clk_hw *hw;
struct clk *parent;
const char **parent_names;
struct clk **parents;
u8 num_parents;
u8 new_parent_index;
unsigned long rate;
unsigned long new_rate;
struct clk *new_parent;
struct clk *new_child;
unsigned long flags;
unsigned int enable_count;
unsigned int prepare_count;
struct hlist_head children;
struct hlist_node child_node;
unsigned int notifier_count;
void *private_data;
#ifdef CONFIG_COMMON_CLK_DEBUG
struct dentry *dentry;
#endif
};
clk结构体是clk子系统的主要结构体,每个clk设备都会抽象为一个clk结构体,这个结构体构建了clk的拓扑关系
2.2 struct clk_hw
struct clk_hw {
struct clk *clk;
const struct clk_init_data *init;
};
clk_hw为不同的clk设备到统一的clk设备搭建桥梁,通过clk_hw就能找到clk_fixed_rate/clk_gate/clk_divider…;比如要找到clk_gate,就可以通过以下宏定义实现:
#define to_clk_gate(_hw) container_of(_hw, struct clk_gate, hw)
2.3clk的相关操作函数ops
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);
unsigned long (*recalc_rate)(struct clk_hw *hw,
unsigned long parent_rate);
long (*round_rate)(struct clk_hw *hw, unsigned long,
unsigned long *);
long (*determine_rate)(struct clk_hw *hw, unsigned long rate,
unsigned long *best_parent_rate,
struct clk **best_parent_clk);
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,
unsigned long);
void (*init)(struct clk_hw *hw);
};
这些操作函数不是每种clk设备都会用到,对于特定的设备只会用到其对应的操作函数,下表总结为:
“y”表示会用到,”-“表示看情况
ops | clk_fixed_rate | clk_gate | clk_divider | clk_mux | clk_fixed_factor | clk_composite |
---|---|---|---|---|---|---|
prepare | - | |||||
unprepare | - | |||||
is_prepared | - | |||||
unprepare_unused | - | |||||
enable | y | - | ||||
disable | y | - | ||||
is_enabled | y | - | ||||
disable_unused | - | |||||
recalc_rate | y | y | y | - | ||
round_rate | y | y | - | |||
determine_rate | y | - | ||||
set_parent | y | - | ||||
get_parent | y | - | ||||
set_rate | y | y | - |
clk源代码在目录drivers/clk:
core的代码源文件为:clkdev.c ,clk-devres.c, clk.c,还有hardware相关的源文件:
clk_fixed_rate | clk_gate | clk_divider | clk_mux | clk_fixed_factor | clk_composite |
---|---|---|---|---|---|
clk-fixed-rate.c | clk-gate.c | clk-divider.c | clk-mux.c | clk-fixed-factor.c | clk-composite.c |
3.clk通用函数接口介绍
这些通用函数接口在头文件include/linux/clk.h中:
clk的打开与关闭:
int clk_enable(struct clk *clk);
void clk_disable(struct clk *clk);
static inline int clk_prepare_enable(struct clk *clk);
static inline void clk_disable_unprepare(struct clk *clk);
clk设备频率:
int clk_set_rate(struct clk *clk, unsigned long rate);
long clk_round_rate(struct clk *clk, unsigned long rate);
unsigned long clk_get_rate(struct clk *clk);
当然还有其他的接口,具体请参考源文件
ref.
linux3.1
更多推荐
所有评论(0)