struct of_clk_provider { struct list_head link;
struct device_node *node; struct clk *(*get)(struct of_phandle_args *clkspec, void *data); struct clk_hw *(*get_hw)(struct of_phandle_args *clkspec, void *data); void *data; };
static LIST_HEAD(of_clk_providers); static DEFINE_MUTEX(of_clk_lock); 添加函数:/** * of_clk_add_provider() - Register a clock provider for a node * @np: Device node pointer associated with clock provider * @clk_src_get: callback for decoding clock * @data: context pointer for @clk_src_get callback. */ int of_clk_add_provider(struct device_node *np, struct clk *(*clk_src_get)(struct of_phandle_args *clkspec, void *data), void *data) { struct of_clk_provider *cp;
cp = kzalloc(sizeof(struct of_clk_provider), GFP_KERNEL); if (!cp) return -ENOMEM;
cp->node = of_node_get(np); cp->data = data; cp->get = clk_src_get;
mutex_lock(&of_clk_lock); list_add(&cp->link, &of_clk_providers); mutex_unlock(&of_clk_lock); pr_debug("Added clock from %s\n", np->full_name);
return 0; }
删除操作 /** * of_clk_del_provider() - Remove a previously registered clock provider * @np: Device node pointer associated with clock provider */ void of_clk_del_provider(struct device_node *np) { struct of_clk_provider *cp;
mutex_lock(&of_clk_lock); list_for_each_entry(cp, &of_clk_providers, link) { if (cp->node == np) { list_del(&cp->link); of_node_put(cp->node); kfree(cp); break; } } mutex_unlock(&of_clk_lock); }
获取clk:
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; }