本文主要是介绍linux驱动-CCF-2 of_clk_provider,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
CCF: common clock frameword
of_clk_provider 总结
1. provider 注册时钟
hws[i] = desc->clk_register(cprman, desc->data);
参考https://mp.csdn.net/mp_blog/creation/editor/138153040
2. provider 注册 of_clk_provider
1. provider 创建了of_clk_provider 结构体,并且存放在全局变量of_clk_providers 中
2. of_clk_provider 提供了data, 和get/get_hw 函数
参考
bcm2835_clk_probe(struct platform_device *pdev)
{ for (i = 0; i < asize; i++) {
desc = &clk_desc_array[i];
if (desc->clk_register && desc->data &&
(desc->supported & pdata->soc)) {
hws[i] = desc->clk_register(cprman, desc->data);
}
}ret = of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,
&cprman->onecell);}
3. consumer 获取 of_clk_provider
假设consumer 设备树节点中存在 clocks = <0x03 0x2d>;
a. 根据0x03 获取 provider 的struct device_node A,
b. 遍历of_clk_providers列表中,of_clk_provier->node 与 A 相等,
则找到provider 的of_clk_provier。
4. consumer 获取时钟
调用of_clk_provier 的get函数, 从of_clk_provier的 data树组中,提取到第0x2d个时钟
参考:
devm_clk_get
clk_get
__of_clk_get_by_name
__of_clk_get
__of_clk_get_from_provider
{list_for_each_entry(provider, &of_clk_providers, link) {
if (provider->node == clkspec->np) {
hw = __of_clk_get_hw_from_provider(provider, clkspec);
clk = __clk_create_clk(hw, dev_id, con_id);
}
}
1. of_clk_provier 结构体
struct of_clk_provider {
struct list_head link;struct device_node *node; //provider 的设备节点
struct clk *(*get)(struct of_phandle_args *clkspec, void *data);//a. data 包含了已经注册的时钟数组
//b. clkspec->args[0]来自于 consumer节点的clocks属性的时钟说明符,
//c. provider 根据 clkspec 查找data 数据,获取指定的时钟
struct clk_hw *(*get_hw)(struct of_phandle_args *clkspec, void *data);
void *data;
};
2. of_clk_provier 初始化并添加
int of_clk_add_hw_provider(struct device_node *np,struct clk_hw *(*get)(struct of_phandle_args *clkspec,void *data),void *data)
{struct of_clk_provider *cp;int ret;cp = kzalloc(sizeof(*cp), GFP_KERNEL);if (!cp)return -ENOMEM;cp->node = of_node_get(np);cp->data = data;cp->get_hw = get;mutex_lock(&of_clk_mutex);list_add(&cp->link, &of_clk_providers); //添加到of_clk_providers 全局链表中mutex_unlock(&of_clk_mutex);pr_debug("Added clk_hw provider from %pOF\n", np);ret = of_clk_set_defaults(np, true);if (ret < 0)of_clk_del_provider(np);return ret;
}
3. 实例- of_clk_provier 的 get/get_hw
=============================================================
ret = of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get, &cprman->onecell);struct clk_hw * of_clk_hw_onecell_get(struct of_phandle_args *clkspec, void *data)
{struct clk_hw_onecell_data *hw_data = data;unsigned int idx = clkspec->args[0];if (idx >= hw_data->num) {pr_err("%s: invalid index %u\n", __func__, idx);return ERR_PTR(-EINVAL);}return hw_data->hws[idx];
}
这篇关于linux驱动-CCF-2 of_clk_provider的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!