xref: /openbmc/linux/drivers/clk/ti/composite.c (revision 3400d546)
15a729246SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2975e1548STero Kristo /*
3975e1548STero Kristo  * TI composite clock support
4975e1548STero Kristo  *
5975e1548STero Kristo  * Copyright (C) 2013 Texas Instruments, Inc.
6975e1548STero Kristo  *
7975e1548STero Kristo  * Tero Kristo <t-kristo@ti.com>
8975e1548STero Kristo  */
9975e1548STero Kristo 
10975e1548STero Kristo #include <linux/clk-provider.h>
11975e1548STero Kristo #include <linux/slab.h>
12975e1548STero Kristo #include <linux/io.h>
13975e1548STero Kristo #include <linux/of.h>
14975e1548STero Kristo #include <linux/of_address.h>
15975e1548STero Kristo #include <linux/clk/ti.h>
16975e1548STero Kristo #include <linux/list.h>
17975e1548STero Kristo 
18b26bcf9bSTero Kristo #include "clock.h"
19b26bcf9bSTero Kristo 
20975e1548STero Kristo #undef pr_fmt
21975e1548STero Kristo #define pr_fmt(fmt) "%s: " fmt, __func__
22975e1548STero Kristo 
ti_composite_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)23975e1548STero Kristo static unsigned long ti_composite_recalc_rate(struct clk_hw *hw,
24975e1548STero Kristo 					      unsigned long parent_rate)
25975e1548STero Kristo {
26b4761198STero Kristo 	return ti_clk_divider_ops.recalc_rate(hw, parent_rate);
27975e1548STero Kristo }
28975e1548STero Kristo 
ti_composite_round_rate(struct clk_hw * hw,unsigned long rate,unsigned long * prate)29975e1548STero Kristo static long ti_composite_round_rate(struct clk_hw *hw, unsigned long rate,
30975e1548STero Kristo 				    unsigned long *prate)
31975e1548STero Kristo {
32975e1548STero Kristo 	return -EINVAL;
33975e1548STero Kristo }
34975e1548STero Kristo 
ti_composite_set_rate(struct clk_hw * hw,unsigned long rate,unsigned long parent_rate)35975e1548STero Kristo static int ti_composite_set_rate(struct clk_hw *hw, unsigned long rate,
36975e1548STero Kristo 				 unsigned long parent_rate)
37975e1548STero Kristo {
38975e1548STero Kristo 	return -EINVAL;
39975e1548STero Kristo }
40975e1548STero Kristo 
41975e1548STero Kristo static const struct clk_ops ti_composite_divider_ops = {
42975e1548STero Kristo 	.recalc_rate	= &ti_composite_recalc_rate,
43975e1548STero Kristo 	.round_rate	= &ti_composite_round_rate,
44975e1548STero Kristo 	.set_rate	= &ti_composite_set_rate,
45975e1548STero Kristo };
46975e1548STero Kristo 
47975e1548STero Kristo static const struct clk_ops ti_composite_gate_ops = {
48975e1548STero Kristo 	.enable		= &omap2_dflt_clk_enable,
49975e1548STero Kristo 	.disable	= &omap2_dflt_clk_disable,
50975e1548STero Kristo 	.is_enabled	= &omap2_dflt_clk_is_enabled,
51975e1548STero Kristo };
52975e1548STero Kristo 
53975e1548STero Kristo struct component_clk {
54975e1548STero Kristo 	int num_parents;
55975e1548STero Kristo 	const char **parent_names;
56975e1548STero Kristo 	struct device_node *node;
57975e1548STero Kristo 	int type;
58975e1548STero Kristo 	struct clk_hw *hw;
59975e1548STero Kristo 	struct list_head link;
60975e1548STero Kristo };
61975e1548STero Kristo 
62692d8328SUwe Kleine-König static const char * const component_clk_types[] __initconst = {
63975e1548STero Kristo 	"gate", "divider", "mux"
64975e1548STero Kristo };
65975e1548STero Kristo 
66975e1548STero Kristo static LIST_HEAD(component_clks);
67975e1548STero Kristo 
_get_component_node(struct device_node * node,int i)68975e1548STero Kristo static struct device_node *_get_component_node(struct device_node *node, int i)
69975e1548STero Kristo {
70975e1548STero Kristo 	int rc;
71975e1548STero Kristo 	struct of_phandle_args clkspec;
72975e1548STero Kristo 
73975e1548STero Kristo 	rc = of_parse_phandle_with_args(node, "clocks", "#clock-cells", i,
74975e1548STero Kristo 					&clkspec);
75975e1548STero Kristo 	if (rc)
76975e1548STero Kristo 		return NULL;
77975e1548STero Kristo 
78975e1548STero Kristo 	return clkspec.np;
79975e1548STero Kristo }
80975e1548STero Kristo 
_lookup_component(struct device_node * node)81975e1548STero Kristo static struct component_clk *_lookup_component(struct device_node *node)
82975e1548STero Kristo {
83975e1548STero Kristo 	struct component_clk *comp;
84975e1548STero Kristo 
85975e1548STero Kristo 	list_for_each_entry(comp, &component_clks, link) {
86975e1548STero Kristo 		if (comp->node == node)
87975e1548STero Kristo 			return comp;
88975e1548STero Kristo 	}
89975e1548STero Kristo 	return NULL;
90975e1548STero Kristo }
91975e1548STero Kristo 
92975e1548STero Kristo struct clk_hw_omap_comp {
93975e1548STero Kristo 	struct clk_hw hw;
94975e1548STero Kristo 	struct device_node *comp_nodes[CLK_COMPONENT_TYPE_MAX];
95975e1548STero Kristo 	struct component_clk *comp_clks[CLK_COMPONENT_TYPE_MAX];
96975e1548STero Kristo };
97975e1548STero Kristo 
_get_hw(struct clk_hw_omap_comp * clk,int idx)98975e1548STero Kristo static inline struct clk_hw *_get_hw(struct clk_hw_omap_comp *clk, int idx)
99975e1548STero Kristo {
100975e1548STero Kristo 	if (!clk)
101975e1548STero Kristo 		return NULL;
102975e1548STero Kristo 
103975e1548STero Kristo 	if (!clk->comp_clks[idx])
104975e1548STero Kristo 		return NULL;
105975e1548STero Kristo 
106975e1548STero Kristo 	return clk->comp_clks[idx]->hw;
107975e1548STero Kristo }
108975e1548STero Kristo 
109975e1548STero Kristo #define to_clk_hw_comp(_hw) container_of(_hw, struct clk_hw_omap_comp, hw)
110975e1548STero Kristo 
_register_composite(void * user,struct device_node * node)111ffb009b2STero Kristo static void __init _register_composite(void *user,
112975e1548STero Kristo 				       struct device_node *node)
113975e1548STero Kristo {
114ffb009b2STero Kristo 	struct clk_hw *hw = user;
115975e1548STero Kristo 	struct clk *clk;
116975e1548STero Kristo 	struct clk_hw_omap_comp *cclk = to_clk_hw_comp(hw);
117975e1548STero Kristo 	struct component_clk *comp;
118975e1548STero Kristo 	int num_parents = 0;
119975e1548STero Kristo 	const char **parent_names = NULL;
120ed06099cSTony Lindgren 	const char *name;
121975e1548STero Kristo 	int i;
1221ae79c46STero Kristo 	int ret;
123975e1548STero Kristo 
124975e1548STero Kristo 	/* Check for presence of each component clock */
125975e1548STero Kristo 	for (i = 0; i < CLK_COMPONENT_TYPE_MAX; i++) {
126975e1548STero Kristo 		if (!cclk->comp_nodes[i])
127975e1548STero Kristo 			continue;
128975e1548STero Kristo 
129975e1548STero Kristo 		comp = _lookup_component(cclk->comp_nodes[i]);
130975e1548STero Kristo 		if (!comp) {
131e665f029SRob Herring 			pr_debug("component %s not ready for %pOFn, retry\n",
132e665f029SRob Herring 				 cclk->comp_nodes[i]->name, node);
133975e1548STero Kristo 			if (!ti_clk_retry_init(node, hw,
134b26bcf9bSTero Kristo 					       _register_composite))
135975e1548STero Kristo 				return;
136975e1548STero Kristo 
137975e1548STero Kristo 			goto cleanup;
138975e1548STero Kristo 		}
139975e1548STero Kristo 		if (cclk->comp_clks[comp->type] != NULL) {
140e665f029SRob Herring 			pr_err("duplicate component types for %pOFn (%s)!\n",
141e665f029SRob Herring 			       node, component_clk_types[comp->type]);
142975e1548STero Kristo 			goto cleanup;
143975e1548STero Kristo 		}
144975e1548STero Kristo 
145975e1548STero Kristo 		cclk->comp_clks[comp->type] = comp;
146975e1548STero Kristo 
147975e1548STero Kristo 		/* Mark this node as found */
148975e1548STero Kristo 		cclk->comp_nodes[i] = NULL;
149975e1548STero Kristo 	}
150975e1548STero Kristo 
151975e1548STero Kristo 	/* All components exists, proceed with registration */
152975e1548STero Kristo 	for (i = CLK_COMPONENT_TYPE_MAX - 1; i >= 0; i--) {
153975e1548STero Kristo 		comp = cclk->comp_clks[i];
154975e1548STero Kristo 		if (!comp)
155975e1548STero Kristo 			continue;
156975e1548STero Kristo 		if (comp->num_parents) {
157975e1548STero Kristo 			num_parents = comp->num_parents;
158975e1548STero Kristo 			parent_names = comp->parent_names;
159975e1548STero Kristo 			break;
160975e1548STero Kristo 		}
161975e1548STero Kristo 	}
162975e1548STero Kristo 
163975e1548STero Kristo 	if (!num_parents) {
164e665f029SRob Herring 		pr_err("%s: no parents found for %pOFn!\n", __func__, node);
165975e1548STero Kristo 		goto cleanup;
166975e1548STero Kristo 	}
167975e1548STero Kristo 
168ed06099cSTony Lindgren 	name = ti_dt_clk_name(node);
169ed06099cSTony Lindgren 	clk = clk_register_composite(NULL, name,
170975e1548STero Kristo 				     parent_names, num_parents,
171975e1548STero Kristo 				     _get_hw(cclk, CLK_COMPONENT_TYPE_MUX),
1726a369c58STero Kristo 				     &ti_clk_mux_ops,
173975e1548STero Kristo 				     _get_hw(cclk, CLK_COMPONENT_TYPE_DIVIDER),
174975e1548STero Kristo 				     &ti_composite_divider_ops,
175975e1548STero Kristo 				     _get_hw(cclk, CLK_COMPONENT_TYPE_GATE),
176975e1548STero Kristo 				     &ti_composite_gate_ops, 0);
177975e1548STero Kristo 
1781ae79c46STero Kristo 	if (!IS_ERR(clk)) {
179*3400d546SDario Binacchi 		ret = ti_clk_add_alias(clk, name);
1801ae79c46STero Kristo 		if (ret) {
1811ae79c46STero Kristo 			clk_unregister(clk);
1821ae79c46STero Kristo 			goto cleanup;
1831ae79c46STero Kristo 		}
184975e1548STero Kristo 		of_clk_add_provider(node, of_clk_src_simple_get, clk);
1851ae79c46STero Kristo 	}
186975e1548STero Kristo 
187975e1548STero Kristo cleanup:
188975e1548STero Kristo 	/* Free component clock list entries */
189975e1548STero Kristo 	for (i = 0; i < CLK_COMPONENT_TYPE_MAX; i++) {
190975e1548STero Kristo 		if (!cclk->comp_clks[i])
191975e1548STero Kristo 			continue;
192975e1548STero Kristo 		list_del(&cclk->comp_clks[i]->link);
193c7c1cbbcSTero Kristo 		kfree(cclk->comp_clks[i]->parent_names);
194975e1548STero Kristo 		kfree(cclk->comp_clks[i]);
195975e1548STero Kristo 	}
196975e1548STero Kristo 
197975e1548STero Kristo 	kfree(cclk);
198975e1548STero Kristo }
199975e1548STero Kristo 
of_ti_composite_clk_setup(struct device_node * node)200975e1548STero Kristo static void __init of_ti_composite_clk_setup(struct device_node *node)
201975e1548STero Kristo {
202921bacfaSStephen Boyd 	unsigned int num_clks;
203975e1548STero Kristo 	int i;
204975e1548STero Kristo 	struct clk_hw_omap_comp *cclk;
205975e1548STero Kristo 
206975e1548STero Kristo 	/* Number of component clocks to be put inside this clock */
207975e1548STero Kristo 	num_clks = of_clk_get_parent_count(node);
208975e1548STero Kristo 
209921bacfaSStephen Boyd 	if (!num_clks) {
210e665f029SRob Herring 		pr_err("composite clk %pOFn must have component(s)\n", node);
211975e1548STero Kristo 		return;
212975e1548STero Kristo 	}
213975e1548STero Kristo 
214975e1548STero Kristo 	cclk = kzalloc(sizeof(*cclk), GFP_KERNEL);
215975e1548STero Kristo 	if (!cclk)
216975e1548STero Kristo 		return;
217975e1548STero Kristo 
218975e1548STero Kristo 	/* Get device node pointers for each component clock */
219975e1548STero Kristo 	for (i = 0; i < num_clks; i++)
220975e1548STero Kristo 		cclk->comp_nodes[i] = _get_component_node(node, i);
221975e1548STero Kristo 
222b26bcf9bSTero Kristo 	_register_composite(&cclk->hw, node);
223975e1548STero Kristo }
224975e1548STero Kristo CLK_OF_DECLARE(ti_composite_clock, "ti,composite-clock",
225975e1548STero Kristo 	       of_ti_composite_clk_setup);
226975e1548STero Kristo 
227975e1548STero Kristo /**
228975e1548STero Kristo  * ti_clk_add_component - add a component clock to the pool
229975e1548STero Kristo  * @node: device node of the component clock
230975e1548STero Kristo  * @hw: hardware clock definition for the component clock
231975e1548STero Kristo  * @type: type of the component clock
232975e1548STero Kristo  *
233975e1548STero Kristo  * Adds a component clock to the list of available components, so that
234975e1548STero Kristo  * it can be registered by a composite clock.
235975e1548STero Kristo  */
ti_clk_add_component(struct device_node * node,struct clk_hw * hw,int type)236975e1548STero Kristo int __init ti_clk_add_component(struct device_node *node, struct clk_hw *hw,
237975e1548STero Kristo 				int type)
238975e1548STero Kristo {
239921bacfaSStephen Boyd 	unsigned int num_parents;
240975e1548STero Kristo 	const char **parent_names;
241975e1548STero Kristo 	struct component_clk *clk;
242975e1548STero Kristo 
243975e1548STero Kristo 	num_parents = of_clk_get_parent_count(node);
244975e1548STero Kristo 
245921bacfaSStephen Boyd 	if (!num_parents) {
246e665f029SRob Herring 		pr_err("component-clock %pOFn must have parent(s)\n", node);
247975e1548STero Kristo 		return -EINVAL;
248975e1548STero Kristo 	}
249975e1548STero Kristo 
25037004db2SLen Baker 	parent_names = kcalloc(num_parents, sizeof(char *), GFP_KERNEL);
251975e1548STero Kristo 	if (!parent_names)
252975e1548STero Kristo 		return -ENOMEM;
253975e1548STero Kristo 
2549da9e761SDinh Nguyen 	of_clk_parent_fill(node, parent_names, num_parents);
255975e1548STero Kristo 
256975e1548STero Kristo 	clk = kzalloc(sizeof(*clk), GFP_KERNEL);
257975e1548STero Kristo 	if (!clk) {
258975e1548STero Kristo 		kfree(parent_names);
259975e1548STero Kristo 		return -ENOMEM;
260975e1548STero Kristo 	}
261975e1548STero Kristo 
262975e1548STero Kristo 	clk->num_parents = num_parents;
263975e1548STero Kristo 	clk->parent_names = parent_names;
264975e1548STero Kristo 	clk->hw = hw;
265975e1548STero Kristo 	clk->node = node;
266975e1548STero Kristo 	clk->type = type;
267975e1548STero Kristo 	list_add(&clk->link, &component_clks);
268975e1548STero Kristo 
269975e1548STero Kristo 	return 0;
270975e1548STero Kristo }
271