xref: /OK3568_Linux_fs/kernel/drivers/clk/ti/divider.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * TI Divider Clock
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Copyright (C) 2013 Texas Instruments, Inc.
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * Tero Kristo <t-kristo@ti.com>
7*4882a593Smuzhiyun  *
8*4882a593Smuzhiyun  * This program is free software; you can redistribute it and/or modify
9*4882a593Smuzhiyun  * it under the terms of the GNU General Public License version 2 as
10*4882a593Smuzhiyun  * published by the Free Software Foundation.
11*4882a593Smuzhiyun  *
12*4882a593Smuzhiyun  * This program is distributed "as is" WITHOUT ANY WARRANTY of any
13*4882a593Smuzhiyun  * kind, whether express or implied; without even the implied warranty
14*4882a593Smuzhiyun  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15*4882a593Smuzhiyun  * GNU General Public License for more details.
16*4882a593Smuzhiyun  */
17*4882a593Smuzhiyun 
18*4882a593Smuzhiyun #include <linux/clk-provider.h>
19*4882a593Smuzhiyun #include <linux/slab.h>
20*4882a593Smuzhiyun #include <linux/err.h>
21*4882a593Smuzhiyun #include <linux/of.h>
22*4882a593Smuzhiyun #include <linux/of_address.h>
23*4882a593Smuzhiyun #include <linux/clk/ti.h>
24*4882a593Smuzhiyun #include "clock.h"
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun #undef pr_fmt
27*4882a593Smuzhiyun #define pr_fmt(fmt) "%s: " fmt, __func__
28*4882a593Smuzhiyun 
_get_table_div(const struct clk_div_table * table,unsigned int val)29*4882a593Smuzhiyun static unsigned int _get_table_div(const struct clk_div_table *table,
30*4882a593Smuzhiyun 				   unsigned int val)
31*4882a593Smuzhiyun {
32*4882a593Smuzhiyun 	const struct clk_div_table *clkt;
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun 	for (clkt = table; clkt->div; clkt++)
35*4882a593Smuzhiyun 		if (clkt->val == val)
36*4882a593Smuzhiyun 			return clkt->div;
37*4882a593Smuzhiyun 	return 0;
38*4882a593Smuzhiyun }
39*4882a593Smuzhiyun 
_setup_mask(struct clk_omap_divider * divider)40*4882a593Smuzhiyun static void _setup_mask(struct clk_omap_divider *divider)
41*4882a593Smuzhiyun {
42*4882a593Smuzhiyun 	u16 mask;
43*4882a593Smuzhiyun 	u32 max_val;
44*4882a593Smuzhiyun 	const struct clk_div_table *clkt;
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun 	if (divider->table) {
47*4882a593Smuzhiyun 		max_val = 0;
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun 		for (clkt = divider->table; clkt->div; clkt++)
50*4882a593Smuzhiyun 			if (clkt->val > max_val)
51*4882a593Smuzhiyun 				max_val = clkt->val;
52*4882a593Smuzhiyun 	} else {
53*4882a593Smuzhiyun 		max_val = divider->max;
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun 		if (!(divider->flags & CLK_DIVIDER_ONE_BASED) &&
56*4882a593Smuzhiyun 		    !(divider->flags & CLK_DIVIDER_POWER_OF_TWO))
57*4882a593Smuzhiyun 			max_val--;
58*4882a593Smuzhiyun 	}
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun 	if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
61*4882a593Smuzhiyun 		mask = fls(max_val) - 1;
62*4882a593Smuzhiyun 	else
63*4882a593Smuzhiyun 		mask = max_val;
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun 	divider->mask = (1 << fls(mask)) - 1;
66*4882a593Smuzhiyun }
67*4882a593Smuzhiyun 
_get_div(struct clk_omap_divider * divider,unsigned int val)68*4882a593Smuzhiyun static unsigned int _get_div(struct clk_omap_divider *divider, unsigned int val)
69*4882a593Smuzhiyun {
70*4882a593Smuzhiyun 	if (divider->flags & CLK_DIVIDER_ONE_BASED)
71*4882a593Smuzhiyun 		return val;
72*4882a593Smuzhiyun 	if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
73*4882a593Smuzhiyun 		return 1 << val;
74*4882a593Smuzhiyun 	if (divider->table)
75*4882a593Smuzhiyun 		return _get_table_div(divider->table, val);
76*4882a593Smuzhiyun 	return val + 1;
77*4882a593Smuzhiyun }
78*4882a593Smuzhiyun 
_get_table_val(const struct clk_div_table * table,unsigned int div)79*4882a593Smuzhiyun static unsigned int _get_table_val(const struct clk_div_table *table,
80*4882a593Smuzhiyun 				   unsigned int div)
81*4882a593Smuzhiyun {
82*4882a593Smuzhiyun 	const struct clk_div_table *clkt;
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun 	for (clkt = table; clkt->div; clkt++)
85*4882a593Smuzhiyun 		if (clkt->div == div)
86*4882a593Smuzhiyun 			return clkt->val;
87*4882a593Smuzhiyun 	return 0;
88*4882a593Smuzhiyun }
89*4882a593Smuzhiyun 
_get_val(struct clk_omap_divider * divider,u8 div)90*4882a593Smuzhiyun static unsigned int _get_val(struct clk_omap_divider *divider, u8 div)
91*4882a593Smuzhiyun {
92*4882a593Smuzhiyun 	if (divider->flags & CLK_DIVIDER_ONE_BASED)
93*4882a593Smuzhiyun 		return div;
94*4882a593Smuzhiyun 	if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
95*4882a593Smuzhiyun 		return __ffs(div);
96*4882a593Smuzhiyun 	if (divider->table)
97*4882a593Smuzhiyun 		return  _get_table_val(divider->table, div);
98*4882a593Smuzhiyun 	return div - 1;
99*4882a593Smuzhiyun }
100*4882a593Smuzhiyun 
ti_clk_divider_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)101*4882a593Smuzhiyun static unsigned long ti_clk_divider_recalc_rate(struct clk_hw *hw,
102*4882a593Smuzhiyun 						unsigned long parent_rate)
103*4882a593Smuzhiyun {
104*4882a593Smuzhiyun 	struct clk_omap_divider *divider = to_clk_omap_divider(hw);
105*4882a593Smuzhiyun 	unsigned int div, val;
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun 	val = ti_clk_ll_ops->clk_readl(&divider->reg) >> divider->shift;
108*4882a593Smuzhiyun 	val &= divider->mask;
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun 	div = _get_div(divider, val);
111*4882a593Smuzhiyun 	if (!div) {
112*4882a593Smuzhiyun 		WARN(!(divider->flags & CLK_DIVIDER_ALLOW_ZERO),
113*4882a593Smuzhiyun 		     "%s: Zero divisor and CLK_DIVIDER_ALLOW_ZERO not set\n",
114*4882a593Smuzhiyun 		     clk_hw_get_name(hw));
115*4882a593Smuzhiyun 		return parent_rate;
116*4882a593Smuzhiyun 	}
117*4882a593Smuzhiyun 
118*4882a593Smuzhiyun 	return DIV_ROUND_UP(parent_rate, div);
119*4882a593Smuzhiyun }
120*4882a593Smuzhiyun 
121*4882a593Smuzhiyun /*
122*4882a593Smuzhiyun  * The reverse of DIV_ROUND_UP: The maximum number which
123*4882a593Smuzhiyun  * divided by m is r
124*4882a593Smuzhiyun  */
125*4882a593Smuzhiyun #define MULT_ROUND_UP(r, m) ((r) * (m) + (m) - 1)
126*4882a593Smuzhiyun 
_is_valid_table_div(const struct clk_div_table * table,unsigned int div)127*4882a593Smuzhiyun static bool _is_valid_table_div(const struct clk_div_table *table,
128*4882a593Smuzhiyun 				unsigned int div)
129*4882a593Smuzhiyun {
130*4882a593Smuzhiyun 	const struct clk_div_table *clkt;
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun 	for (clkt = table; clkt->div; clkt++)
133*4882a593Smuzhiyun 		if (clkt->div == div)
134*4882a593Smuzhiyun 			return true;
135*4882a593Smuzhiyun 	return false;
136*4882a593Smuzhiyun }
137*4882a593Smuzhiyun 
_is_valid_div(struct clk_omap_divider * divider,unsigned int div)138*4882a593Smuzhiyun static bool _is_valid_div(struct clk_omap_divider *divider, unsigned int div)
139*4882a593Smuzhiyun {
140*4882a593Smuzhiyun 	if (divider->flags & CLK_DIVIDER_POWER_OF_TWO)
141*4882a593Smuzhiyun 		return is_power_of_2(div);
142*4882a593Smuzhiyun 	if (divider->table)
143*4882a593Smuzhiyun 		return _is_valid_table_div(divider->table, div);
144*4882a593Smuzhiyun 	return true;
145*4882a593Smuzhiyun }
146*4882a593Smuzhiyun 
_div_round_up(const struct clk_div_table * table,unsigned long parent_rate,unsigned long rate)147*4882a593Smuzhiyun static int _div_round_up(const struct clk_div_table *table,
148*4882a593Smuzhiyun 			 unsigned long parent_rate, unsigned long rate)
149*4882a593Smuzhiyun {
150*4882a593Smuzhiyun 	const struct clk_div_table *clkt;
151*4882a593Smuzhiyun 	int up = INT_MAX;
152*4882a593Smuzhiyun 	int div = DIV_ROUND_UP_ULL((u64)parent_rate, rate);
153*4882a593Smuzhiyun 
154*4882a593Smuzhiyun 	for (clkt = table; clkt->div; clkt++) {
155*4882a593Smuzhiyun 		if (clkt->div == div)
156*4882a593Smuzhiyun 			return clkt->div;
157*4882a593Smuzhiyun 		else if (clkt->div < div)
158*4882a593Smuzhiyun 			continue;
159*4882a593Smuzhiyun 
160*4882a593Smuzhiyun 		if ((clkt->div - div) < (up - div))
161*4882a593Smuzhiyun 			up = clkt->div;
162*4882a593Smuzhiyun 	}
163*4882a593Smuzhiyun 
164*4882a593Smuzhiyun 	return up;
165*4882a593Smuzhiyun }
166*4882a593Smuzhiyun 
_div_round(const struct clk_div_table * table,unsigned long parent_rate,unsigned long rate)167*4882a593Smuzhiyun static int _div_round(const struct clk_div_table *table,
168*4882a593Smuzhiyun 		      unsigned long parent_rate, unsigned long rate)
169*4882a593Smuzhiyun {
170*4882a593Smuzhiyun 	if (!table)
171*4882a593Smuzhiyun 		return DIV_ROUND_UP(parent_rate, rate);
172*4882a593Smuzhiyun 
173*4882a593Smuzhiyun 	return _div_round_up(table, parent_rate, rate);
174*4882a593Smuzhiyun }
175*4882a593Smuzhiyun 
ti_clk_divider_bestdiv(struct clk_hw * hw,unsigned long rate,unsigned long * best_parent_rate)176*4882a593Smuzhiyun static int ti_clk_divider_bestdiv(struct clk_hw *hw, unsigned long rate,
177*4882a593Smuzhiyun 				  unsigned long *best_parent_rate)
178*4882a593Smuzhiyun {
179*4882a593Smuzhiyun 	struct clk_omap_divider *divider = to_clk_omap_divider(hw);
180*4882a593Smuzhiyun 	int i, bestdiv = 0;
181*4882a593Smuzhiyun 	unsigned long parent_rate, best = 0, now, maxdiv;
182*4882a593Smuzhiyun 	unsigned long parent_rate_saved = *best_parent_rate;
183*4882a593Smuzhiyun 
184*4882a593Smuzhiyun 	if (!rate)
185*4882a593Smuzhiyun 		rate = 1;
186*4882a593Smuzhiyun 
187*4882a593Smuzhiyun 	maxdiv = divider->max;
188*4882a593Smuzhiyun 
189*4882a593Smuzhiyun 	if (!(clk_hw_get_flags(hw) & CLK_SET_RATE_PARENT)) {
190*4882a593Smuzhiyun 		parent_rate = *best_parent_rate;
191*4882a593Smuzhiyun 		bestdiv = _div_round(divider->table, parent_rate, rate);
192*4882a593Smuzhiyun 		bestdiv = bestdiv == 0 ? 1 : bestdiv;
193*4882a593Smuzhiyun 		bestdiv = bestdiv > maxdiv ? maxdiv : bestdiv;
194*4882a593Smuzhiyun 		return bestdiv;
195*4882a593Smuzhiyun 	}
196*4882a593Smuzhiyun 
197*4882a593Smuzhiyun 	/*
198*4882a593Smuzhiyun 	 * The maximum divider we can use without overflowing
199*4882a593Smuzhiyun 	 * unsigned long in rate * i below
200*4882a593Smuzhiyun 	 */
201*4882a593Smuzhiyun 	maxdiv = min(ULONG_MAX / rate, maxdiv);
202*4882a593Smuzhiyun 
203*4882a593Smuzhiyun 	for (i = 1; i <= maxdiv; i++) {
204*4882a593Smuzhiyun 		if (!_is_valid_div(divider, i))
205*4882a593Smuzhiyun 			continue;
206*4882a593Smuzhiyun 		if (rate * i == parent_rate_saved) {
207*4882a593Smuzhiyun 			/*
208*4882a593Smuzhiyun 			 * It's the most ideal case if the requested rate can be
209*4882a593Smuzhiyun 			 * divided from parent clock without needing to change
210*4882a593Smuzhiyun 			 * parent rate, so return the divider immediately.
211*4882a593Smuzhiyun 			 */
212*4882a593Smuzhiyun 			*best_parent_rate = parent_rate_saved;
213*4882a593Smuzhiyun 			return i;
214*4882a593Smuzhiyun 		}
215*4882a593Smuzhiyun 		parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw),
216*4882a593Smuzhiyun 				MULT_ROUND_UP(rate, i));
217*4882a593Smuzhiyun 		now = DIV_ROUND_UP(parent_rate, i);
218*4882a593Smuzhiyun 		if (now <= rate && now > best) {
219*4882a593Smuzhiyun 			bestdiv = i;
220*4882a593Smuzhiyun 			best = now;
221*4882a593Smuzhiyun 			*best_parent_rate = parent_rate;
222*4882a593Smuzhiyun 		}
223*4882a593Smuzhiyun 	}
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun 	if (!bestdiv) {
226*4882a593Smuzhiyun 		bestdiv = divider->max;
227*4882a593Smuzhiyun 		*best_parent_rate =
228*4882a593Smuzhiyun 			clk_hw_round_rate(clk_hw_get_parent(hw), 1);
229*4882a593Smuzhiyun 	}
230*4882a593Smuzhiyun 
231*4882a593Smuzhiyun 	return bestdiv;
232*4882a593Smuzhiyun }
233*4882a593Smuzhiyun 
ti_clk_divider_round_rate(struct clk_hw * hw,unsigned long rate,unsigned long * prate)234*4882a593Smuzhiyun static long ti_clk_divider_round_rate(struct clk_hw *hw, unsigned long rate,
235*4882a593Smuzhiyun 				      unsigned long *prate)
236*4882a593Smuzhiyun {
237*4882a593Smuzhiyun 	int div;
238*4882a593Smuzhiyun 	div = ti_clk_divider_bestdiv(hw, rate, prate);
239*4882a593Smuzhiyun 
240*4882a593Smuzhiyun 	return DIV_ROUND_UP(*prate, div);
241*4882a593Smuzhiyun }
242*4882a593Smuzhiyun 
ti_clk_divider_set_rate(struct clk_hw * hw,unsigned long rate,unsigned long parent_rate)243*4882a593Smuzhiyun static int ti_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate,
244*4882a593Smuzhiyun 				   unsigned long parent_rate)
245*4882a593Smuzhiyun {
246*4882a593Smuzhiyun 	struct clk_omap_divider *divider;
247*4882a593Smuzhiyun 	unsigned int div, value;
248*4882a593Smuzhiyun 	u32 val;
249*4882a593Smuzhiyun 
250*4882a593Smuzhiyun 	if (!hw || !rate)
251*4882a593Smuzhiyun 		return -EINVAL;
252*4882a593Smuzhiyun 
253*4882a593Smuzhiyun 	divider = to_clk_omap_divider(hw);
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun 	div = DIV_ROUND_UP(parent_rate, rate);
256*4882a593Smuzhiyun 
257*4882a593Smuzhiyun 	if (div > divider->max)
258*4882a593Smuzhiyun 		div = divider->max;
259*4882a593Smuzhiyun 	if (div < divider->min)
260*4882a593Smuzhiyun 		div = divider->min;
261*4882a593Smuzhiyun 
262*4882a593Smuzhiyun 	value = _get_val(divider, div);
263*4882a593Smuzhiyun 
264*4882a593Smuzhiyun 	val = ti_clk_ll_ops->clk_readl(&divider->reg);
265*4882a593Smuzhiyun 	val &= ~(divider->mask << divider->shift);
266*4882a593Smuzhiyun 	val |= value << divider->shift;
267*4882a593Smuzhiyun 	ti_clk_ll_ops->clk_writel(val, &divider->reg);
268*4882a593Smuzhiyun 
269*4882a593Smuzhiyun 	ti_clk_latch(&divider->reg, divider->latch);
270*4882a593Smuzhiyun 
271*4882a593Smuzhiyun 	return 0;
272*4882a593Smuzhiyun }
273*4882a593Smuzhiyun 
274*4882a593Smuzhiyun /**
275*4882a593Smuzhiyun  * clk_divider_save_context - Save the divider value
276*4882a593Smuzhiyun  * @hw: pointer  struct clk_hw
277*4882a593Smuzhiyun  *
278*4882a593Smuzhiyun  * Save the divider value
279*4882a593Smuzhiyun  */
clk_divider_save_context(struct clk_hw * hw)280*4882a593Smuzhiyun static int clk_divider_save_context(struct clk_hw *hw)
281*4882a593Smuzhiyun {
282*4882a593Smuzhiyun 	struct clk_omap_divider *divider = to_clk_omap_divider(hw);
283*4882a593Smuzhiyun 	u32 val;
284*4882a593Smuzhiyun 
285*4882a593Smuzhiyun 	val = ti_clk_ll_ops->clk_readl(&divider->reg) >> divider->shift;
286*4882a593Smuzhiyun 	divider->context = val & divider->mask;
287*4882a593Smuzhiyun 
288*4882a593Smuzhiyun 	return 0;
289*4882a593Smuzhiyun }
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun /**
292*4882a593Smuzhiyun  * clk_divider_restore_context - restore the saved the divider value
293*4882a593Smuzhiyun  * @hw: pointer  struct clk_hw
294*4882a593Smuzhiyun  *
295*4882a593Smuzhiyun  * Restore the saved the divider value
296*4882a593Smuzhiyun  */
clk_divider_restore_context(struct clk_hw * hw)297*4882a593Smuzhiyun static void clk_divider_restore_context(struct clk_hw *hw)
298*4882a593Smuzhiyun {
299*4882a593Smuzhiyun 	struct clk_omap_divider *divider = to_clk_omap_divider(hw);
300*4882a593Smuzhiyun 	u32 val;
301*4882a593Smuzhiyun 
302*4882a593Smuzhiyun 	val = ti_clk_ll_ops->clk_readl(&divider->reg);
303*4882a593Smuzhiyun 	val &= ~(divider->mask << divider->shift);
304*4882a593Smuzhiyun 	val |= divider->context << divider->shift;
305*4882a593Smuzhiyun 	ti_clk_ll_ops->clk_writel(val, &divider->reg);
306*4882a593Smuzhiyun }
307*4882a593Smuzhiyun 
308*4882a593Smuzhiyun const struct clk_ops ti_clk_divider_ops = {
309*4882a593Smuzhiyun 	.recalc_rate = ti_clk_divider_recalc_rate,
310*4882a593Smuzhiyun 	.round_rate = ti_clk_divider_round_rate,
311*4882a593Smuzhiyun 	.set_rate = ti_clk_divider_set_rate,
312*4882a593Smuzhiyun 	.save_context = clk_divider_save_context,
313*4882a593Smuzhiyun 	.restore_context = clk_divider_restore_context,
314*4882a593Smuzhiyun };
315*4882a593Smuzhiyun 
_register_divider(struct device_node * node,u32 flags,struct clk_omap_divider * div)316*4882a593Smuzhiyun static struct clk *_register_divider(struct device_node *node,
317*4882a593Smuzhiyun 				     u32 flags,
318*4882a593Smuzhiyun 				     struct clk_omap_divider *div)
319*4882a593Smuzhiyun {
320*4882a593Smuzhiyun 	struct clk *clk;
321*4882a593Smuzhiyun 	struct clk_init_data init;
322*4882a593Smuzhiyun 	const char *parent_name;
323*4882a593Smuzhiyun 
324*4882a593Smuzhiyun 	parent_name = of_clk_get_parent_name(node, 0);
325*4882a593Smuzhiyun 
326*4882a593Smuzhiyun 	init.name = node->name;
327*4882a593Smuzhiyun 	init.ops = &ti_clk_divider_ops;
328*4882a593Smuzhiyun 	init.flags = flags;
329*4882a593Smuzhiyun 	init.parent_names = (parent_name ? &parent_name : NULL);
330*4882a593Smuzhiyun 	init.num_parents = (parent_name ? 1 : 0);
331*4882a593Smuzhiyun 
332*4882a593Smuzhiyun 	div->hw.init = &init;
333*4882a593Smuzhiyun 
334*4882a593Smuzhiyun 	/* register the clock */
335*4882a593Smuzhiyun 	clk = ti_clk_register(NULL, &div->hw, node->name);
336*4882a593Smuzhiyun 
337*4882a593Smuzhiyun 	if (IS_ERR(clk))
338*4882a593Smuzhiyun 		kfree(div);
339*4882a593Smuzhiyun 
340*4882a593Smuzhiyun 	return clk;
341*4882a593Smuzhiyun }
342*4882a593Smuzhiyun 
ti_clk_parse_divider_data(int * div_table,int num_dividers,int max_div,u8 flags,struct clk_omap_divider * divider)343*4882a593Smuzhiyun int ti_clk_parse_divider_data(int *div_table, int num_dividers, int max_div,
344*4882a593Smuzhiyun 			      u8 flags, struct clk_omap_divider *divider)
345*4882a593Smuzhiyun {
346*4882a593Smuzhiyun 	int valid_div = 0;
347*4882a593Smuzhiyun 	int i;
348*4882a593Smuzhiyun 	struct clk_div_table *tmp;
349*4882a593Smuzhiyun 	u16 min_div = 0;
350*4882a593Smuzhiyun 
351*4882a593Smuzhiyun 	if (!div_table) {
352*4882a593Smuzhiyun 		divider->min = 1;
353*4882a593Smuzhiyun 		divider->max = max_div;
354*4882a593Smuzhiyun 		_setup_mask(divider);
355*4882a593Smuzhiyun 		return 0;
356*4882a593Smuzhiyun 	}
357*4882a593Smuzhiyun 
358*4882a593Smuzhiyun 	i = 0;
359*4882a593Smuzhiyun 
360*4882a593Smuzhiyun 	while (!num_dividers || i < num_dividers) {
361*4882a593Smuzhiyun 		if (div_table[i] == -1)
362*4882a593Smuzhiyun 			break;
363*4882a593Smuzhiyun 		if (div_table[i])
364*4882a593Smuzhiyun 			valid_div++;
365*4882a593Smuzhiyun 		i++;
366*4882a593Smuzhiyun 	}
367*4882a593Smuzhiyun 
368*4882a593Smuzhiyun 	num_dividers = i;
369*4882a593Smuzhiyun 
370*4882a593Smuzhiyun 	tmp = kcalloc(valid_div + 1, sizeof(*tmp), GFP_KERNEL);
371*4882a593Smuzhiyun 	if (!tmp)
372*4882a593Smuzhiyun 		return -ENOMEM;
373*4882a593Smuzhiyun 
374*4882a593Smuzhiyun 	valid_div = 0;
375*4882a593Smuzhiyun 
376*4882a593Smuzhiyun 	for (i = 0; i < num_dividers; i++)
377*4882a593Smuzhiyun 		if (div_table[i] > 0) {
378*4882a593Smuzhiyun 			tmp[valid_div].div = div_table[i];
379*4882a593Smuzhiyun 			tmp[valid_div].val = i;
380*4882a593Smuzhiyun 			valid_div++;
381*4882a593Smuzhiyun 			if (div_table[i] > max_div)
382*4882a593Smuzhiyun 				max_div = div_table[i];
383*4882a593Smuzhiyun 			if (!min_div || div_table[i] < min_div)
384*4882a593Smuzhiyun 				min_div = div_table[i];
385*4882a593Smuzhiyun 		}
386*4882a593Smuzhiyun 
387*4882a593Smuzhiyun 	divider->min = min_div;
388*4882a593Smuzhiyun 	divider->max = max_div;
389*4882a593Smuzhiyun 	divider->table = tmp;
390*4882a593Smuzhiyun 	_setup_mask(divider);
391*4882a593Smuzhiyun 
392*4882a593Smuzhiyun 	return 0;
393*4882a593Smuzhiyun }
394*4882a593Smuzhiyun 
ti_clk_get_div_table(struct device_node * node,struct clk_omap_divider * div)395*4882a593Smuzhiyun static int __init ti_clk_get_div_table(struct device_node *node,
396*4882a593Smuzhiyun 				       struct clk_omap_divider *div)
397*4882a593Smuzhiyun {
398*4882a593Smuzhiyun 	struct clk_div_table *table;
399*4882a593Smuzhiyun 	const __be32 *divspec;
400*4882a593Smuzhiyun 	u32 val;
401*4882a593Smuzhiyun 	u32 num_div;
402*4882a593Smuzhiyun 	u32 valid_div;
403*4882a593Smuzhiyun 	int i;
404*4882a593Smuzhiyun 
405*4882a593Smuzhiyun 	divspec = of_get_property(node, "ti,dividers", &num_div);
406*4882a593Smuzhiyun 
407*4882a593Smuzhiyun 	if (!divspec)
408*4882a593Smuzhiyun 		return 0;
409*4882a593Smuzhiyun 
410*4882a593Smuzhiyun 	num_div /= 4;
411*4882a593Smuzhiyun 
412*4882a593Smuzhiyun 	valid_div = 0;
413*4882a593Smuzhiyun 
414*4882a593Smuzhiyun 	/* Determine required size for divider table */
415*4882a593Smuzhiyun 	for (i = 0; i < num_div; i++) {
416*4882a593Smuzhiyun 		of_property_read_u32_index(node, "ti,dividers", i, &val);
417*4882a593Smuzhiyun 		if (val)
418*4882a593Smuzhiyun 			valid_div++;
419*4882a593Smuzhiyun 	}
420*4882a593Smuzhiyun 
421*4882a593Smuzhiyun 	if (!valid_div) {
422*4882a593Smuzhiyun 		pr_err("no valid dividers for %pOFn table\n", node);
423*4882a593Smuzhiyun 		return -EINVAL;
424*4882a593Smuzhiyun 	}
425*4882a593Smuzhiyun 
426*4882a593Smuzhiyun 	table = kcalloc(valid_div + 1, sizeof(*table), GFP_KERNEL);
427*4882a593Smuzhiyun 	if (!table)
428*4882a593Smuzhiyun 		return -ENOMEM;
429*4882a593Smuzhiyun 
430*4882a593Smuzhiyun 	valid_div = 0;
431*4882a593Smuzhiyun 
432*4882a593Smuzhiyun 	for (i = 0; i < num_div; i++) {
433*4882a593Smuzhiyun 		of_property_read_u32_index(node, "ti,dividers", i, &val);
434*4882a593Smuzhiyun 		if (val) {
435*4882a593Smuzhiyun 			table[valid_div].div = val;
436*4882a593Smuzhiyun 			table[valid_div].val = i;
437*4882a593Smuzhiyun 			valid_div++;
438*4882a593Smuzhiyun 		}
439*4882a593Smuzhiyun 	}
440*4882a593Smuzhiyun 
441*4882a593Smuzhiyun 	div->table = table;
442*4882a593Smuzhiyun 
443*4882a593Smuzhiyun 	return 0;
444*4882a593Smuzhiyun }
445*4882a593Smuzhiyun 
_populate_divider_min_max(struct device_node * node,struct clk_omap_divider * divider)446*4882a593Smuzhiyun static int _populate_divider_min_max(struct device_node *node,
447*4882a593Smuzhiyun 				     struct clk_omap_divider *divider)
448*4882a593Smuzhiyun {
449*4882a593Smuzhiyun 	u32 min_div = 0;
450*4882a593Smuzhiyun 	u32 max_div = 0;
451*4882a593Smuzhiyun 	u32 val;
452*4882a593Smuzhiyun 	const struct clk_div_table *clkt;
453*4882a593Smuzhiyun 
454*4882a593Smuzhiyun 	if (!divider->table) {
455*4882a593Smuzhiyun 		/* Clk divider table not provided, determine min/max divs */
456*4882a593Smuzhiyun 		if (of_property_read_u32(node, "ti,min-div", &min_div))
457*4882a593Smuzhiyun 			min_div = 1;
458*4882a593Smuzhiyun 
459*4882a593Smuzhiyun 		if (of_property_read_u32(node, "ti,max-div", &max_div)) {
460*4882a593Smuzhiyun 			pr_err("no max-div for %pOFn!\n", node);
461*4882a593Smuzhiyun 			return -EINVAL;
462*4882a593Smuzhiyun 		}
463*4882a593Smuzhiyun 	} else {
464*4882a593Smuzhiyun 
465*4882a593Smuzhiyun 		for (clkt = divider->table; clkt->div; clkt++) {
466*4882a593Smuzhiyun 			val = clkt->div;
467*4882a593Smuzhiyun 			if (val > max_div)
468*4882a593Smuzhiyun 				max_div = val;
469*4882a593Smuzhiyun 			if (!min_div || val < min_div)
470*4882a593Smuzhiyun 				min_div = val;
471*4882a593Smuzhiyun 		}
472*4882a593Smuzhiyun 	}
473*4882a593Smuzhiyun 
474*4882a593Smuzhiyun 	divider->min = min_div;
475*4882a593Smuzhiyun 	divider->max = max_div;
476*4882a593Smuzhiyun 	_setup_mask(divider);
477*4882a593Smuzhiyun 
478*4882a593Smuzhiyun 	return 0;
479*4882a593Smuzhiyun }
480*4882a593Smuzhiyun 
ti_clk_divider_populate(struct device_node * node,struct clk_omap_divider * div,u32 * flags)481*4882a593Smuzhiyun static int __init ti_clk_divider_populate(struct device_node *node,
482*4882a593Smuzhiyun 					  struct clk_omap_divider *div,
483*4882a593Smuzhiyun 					  u32 *flags)
484*4882a593Smuzhiyun {
485*4882a593Smuzhiyun 	u32 val;
486*4882a593Smuzhiyun 	int ret;
487*4882a593Smuzhiyun 
488*4882a593Smuzhiyun 	ret = ti_clk_get_reg_addr(node, 0, &div->reg);
489*4882a593Smuzhiyun 	if (ret)
490*4882a593Smuzhiyun 		return ret;
491*4882a593Smuzhiyun 
492*4882a593Smuzhiyun 	if (!of_property_read_u32(node, "ti,bit-shift", &val))
493*4882a593Smuzhiyun 		div->shift = val;
494*4882a593Smuzhiyun 	else
495*4882a593Smuzhiyun 		div->shift = 0;
496*4882a593Smuzhiyun 
497*4882a593Smuzhiyun 	if (!of_property_read_u32(node, "ti,latch-bit", &val))
498*4882a593Smuzhiyun 		div->latch = val;
499*4882a593Smuzhiyun 	else
500*4882a593Smuzhiyun 		div->latch = -EINVAL;
501*4882a593Smuzhiyun 
502*4882a593Smuzhiyun 	*flags = 0;
503*4882a593Smuzhiyun 	div->flags = 0;
504*4882a593Smuzhiyun 
505*4882a593Smuzhiyun 	if (of_property_read_bool(node, "ti,index-starts-at-one"))
506*4882a593Smuzhiyun 		div->flags |= CLK_DIVIDER_ONE_BASED;
507*4882a593Smuzhiyun 
508*4882a593Smuzhiyun 	if (of_property_read_bool(node, "ti,index-power-of-two"))
509*4882a593Smuzhiyun 		div->flags |= CLK_DIVIDER_POWER_OF_TWO;
510*4882a593Smuzhiyun 
511*4882a593Smuzhiyun 	if (of_property_read_bool(node, "ti,set-rate-parent"))
512*4882a593Smuzhiyun 		*flags |= CLK_SET_RATE_PARENT;
513*4882a593Smuzhiyun 
514*4882a593Smuzhiyun 	ret = ti_clk_get_div_table(node, div);
515*4882a593Smuzhiyun 	if (ret)
516*4882a593Smuzhiyun 		return ret;
517*4882a593Smuzhiyun 
518*4882a593Smuzhiyun 	return _populate_divider_min_max(node, div);
519*4882a593Smuzhiyun }
520*4882a593Smuzhiyun 
521*4882a593Smuzhiyun /**
522*4882a593Smuzhiyun  * of_ti_divider_clk_setup - Setup function for simple div rate clock
523*4882a593Smuzhiyun  * @node: device node for this clock
524*4882a593Smuzhiyun  *
525*4882a593Smuzhiyun  * Sets up a basic divider clock.
526*4882a593Smuzhiyun  */
of_ti_divider_clk_setup(struct device_node * node)527*4882a593Smuzhiyun static void __init of_ti_divider_clk_setup(struct device_node *node)
528*4882a593Smuzhiyun {
529*4882a593Smuzhiyun 	struct clk *clk;
530*4882a593Smuzhiyun 	u32 flags = 0;
531*4882a593Smuzhiyun 	struct clk_omap_divider *div;
532*4882a593Smuzhiyun 
533*4882a593Smuzhiyun 	div = kzalloc(sizeof(*div), GFP_KERNEL);
534*4882a593Smuzhiyun 	if (!div)
535*4882a593Smuzhiyun 		return;
536*4882a593Smuzhiyun 
537*4882a593Smuzhiyun 	if (ti_clk_divider_populate(node, div, &flags))
538*4882a593Smuzhiyun 		goto cleanup;
539*4882a593Smuzhiyun 
540*4882a593Smuzhiyun 	clk = _register_divider(node, flags, div);
541*4882a593Smuzhiyun 	if (!IS_ERR(clk)) {
542*4882a593Smuzhiyun 		of_clk_add_provider(node, of_clk_src_simple_get, clk);
543*4882a593Smuzhiyun 		of_ti_clk_autoidle_setup(node);
544*4882a593Smuzhiyun 		return;
545*4882a593Smuzhiyun 	}
546*4882a593Smuzhiyun 
547*4882a593Smuzhiyun cleanup:
548*4882a593Smuzhiyun 	kfree(div->table);
549*4882a593Smuzhiyun 	kfree(div);
550*4882a593Smuzhiyun }
551*4882a593Smuzhiyun CLK_OF_DECLARE(divider_clk, "ti,divider-clock", of_ti_divider_clk_setup);
552*4882a593Smuzhiyun 
of_ti_composite_divider_clk_setup(struct device_node * node)553*4882a593Smuzhiyun static void __init of_ti_composite_divider_clk_setup(struct device_node *node)
554*4882a593Smuzhiyun {
555*4882a593Smuzhiyun 	struct clk_omap_divider *div;
556*4882a593Smuzhiyun 	u32 tmp;
557*4882a593Smuzhiyun 
558*4882a593Smuzhiyun 	div = kzalloc(sizeof(*div), GFP_KERNEL);
559*4882a593Smuzhiyun 	if (!div)
560*4882a593Smuzhiyun 		return;
561*4882a593Smuzhiyun 
562*4882a593Smuzhiyun 	if (ti_clk_divider_populate(node, div, &tmp))
563*4882a593Smuzhiyun 		goto cleanup;
564*4882a593Smuzhiyun 
565*4882a593Smuzhiyun 	if (!ti_clk_add_component(node, &div->hw, CLK_COMPONENT_TYPE_DIVIDER))
566*4882a593Smuzhiyun 		return;
567*4882a593Smuzhiyun 
568*4882a593Smuzhiyun cleanup:
569*4882a593Smuzhiyun 	kfree(div->table);
570*4882a593Smuzhiyun 	kfree(div);
571*4882a593Smuzhiyun }
572*4882a593Smuzhiyun CLK_OF_DECLARE(ti_composite_divider_clk, "ti,composite-divider-clock",
573*4882a593Smuzhiyun 	       of_ti_composite_divider_clk_setup);
574