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