当前位置:   article > 正文

linux驱动-CCF-2 of_clk_provider

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 初始化并添加

  1. int of_clk_add_hw_provider(struct device_node *np,
  2. struct clk_hw *(*get)(struct of_phandle_args *clkspec,
  3. void *data),
  4. void *data)
  5. {
  6. struct of_clk_provider *cp;
  7. int ret;
  8. cp = kzalloc(sizeof(*cp), GFP_KERNEL);
  9. if (!cp)
  10. return -ENOMEM;
  11. cp->node = of_node_get(np);
  12. cp->data = data;
  13. cp->get_hw = get;
  14. mutex_lock(&of_clk_mutex);
  15. list_add(&cp->link, &of_clk_providers); //添加到of_clk_providers 全局链表中
  16. mutex_unlock(&of_clk_mutex);
  17. pr_debug("Added clk_hw provider from %pOF\n", np);
  18. ret = of_clk_set_defaults(np, true);
  19. if (ret < 0)
  20. of_clk_del_provider(np);
  21. return ret;
  22. }

 3. 实例- of_clk_provier 的 get/get_hw

  1. =============================================================
  2. ret = of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get, &cprman->onecell);
  3. struct clk_hw * of_clk_hw_onecell_get(struct of_phandle_args *clkspec, void *data)
  4. {
  5. struct clk_hw_onecell_data *hw_data = data;
  6. unsigned int idx = clkspec->args[0];
  7. if (idx >= hw_data->num) {
  8. pr_err("%s: invalid index %u\n", __func__, idx);
  9. return ERR_PTR(-EINVAL);
  10. }
  11. return hw_data->hws[idx];
  12. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/484373
推荐阅读
相关标签
  

闽ICP备14008679号