xref: /openbmc/linux/drivers/clk/qcom/clk-rcg2.c (revision afc98d90)
1 /*
2  * Copyright (c) 2013, The Linux Foundation. All rights reserved.
3  *
4  * This software is licensed under the terms of the GNU General Public
5  * License version 2, as published by the Free Software Foundation, and
6  * may be copied, distributed, and modified under those terms.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  */
13 
14 #include <linux/kernel.h>
15 #include <linux/bitops.h>
16 #include <linux/err.h>
17 #include <linux/bug.h>
18 #include <linux/export.h>
19 #include <linux/clk-provider.h>
20 #include <linux/delay.h>
21 #include <linux/regmap.h>
22 
23 #include <asm/div64.h>
24 
25 #include "clk-rcg.h"
26 
27 #define CMD_REG			0x0
28 #define CMD_UPDATE		BIT(0)
29 #define CMD_ROOT_EN		BIT(1)
30 #define CMD_DIRTY_CFG		BIT(4)
31 #define CMD_DIRTY_N		BIT(5)
32 #define CMD_DIRTY_M		BIT(6)
33 #define CMD_DIRTY_D		BIT(7)
34 #define CMD_ROOT_OFF		BIT(31)
35 
36 #define CFG_REG			0x4
37 #define CFG_SRC_DIV_SHIFT	0
38 #define CFG_SRC_SEL_SHIFT	8
39 #define CFG_SRC_SEL_MASK	(0x7 << CFG_SRC_SEL_SHIFT)
40 #define CFG_MODE_SHIFT		12
41 #define CFG_MODE_MASK		(0x3 << CFG_MODE_SHIFT)
42 #define CFG_MODE_DUAL_EDGE	(0x2 << CFG_MODE_SHIFT)
43 
44 #define M_REG			0x8
45 #define N_REG			0xc
46 #define D_REG			0x10
47 
48 static int clk_rcg2_is_enabled(struct clk_hw *hw)
49 {
50 	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
51 	u32 cmd;
52 	int ret;
53 
54 	ret = regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CMD_REG, &cmd);
55 	if (ret)
56 		return ret;
57 
58 	return (cmd & CMD_ROOT_OFF) != 0;
59 }
60 
61 static u8 clk_rcg2_get_parent(struct clk_hw *hw)
62 {
63 	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
64 	int num_parents = __clk_get_num_parents(hw->clk);
65 	u32 cfg;
66 	int i, ret;
67 
68 	ret = regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, &cfg);
69 	if (ret)
70 		return ret;
71 
72 	cfg &= CFG_SRC_SEL_MASK;
73 	cfg >>= CFG_SRC_SEL_SHIFT;
74 
75 	for (i = 0; i < num_parents; i++)
76 		if (cfg == rcg->parent_map[i])
77 			return i;
78 
79 	return -EINVAL;
80 }
81 
82 static int update_config(struct clk_rcg2 *rcg)
83 {
84 	int count, ret;
85 	u32 cmd;
86 	struct clk_hw *hw = &rcg->clkr.hw;
87 	const char *name = __clk_get_name(hw->clk);
88 
89 	ret = regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + CMD_REG,
90 				 CMD_UPDATE, CMD_UPDATE);
91 	if (ret)
92 		return ret;
93 
94 	/* Wait for update to take effect */
95 	for (count = 500; count > 0; count--) {
96 		ret = regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CMD_REG, &cmd);
97 		if (ret)
98 			return ret;
99 		if (!(cmd & CMD_UPDATE))
100 			return 0;
101 		udelay(1);
102 	}
103 
104 	WARN(1, "%s: rcg didn't update its configuration.", name);
105 	return 0;
106 }
107 
108 static int clk_rcg2_set_parent(struct clk_hw *hw, u8 index)
109 {
110 	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
111 	int ret;
112 
113 	ret = regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG,
114 				 CFG_SRC_SEL_MASK,
115 				 rcg->parent_map[index] << CFG_SRC_SEL_SHIFT);
116 	if (ret)
117 		return ret;
118 
119 	return update_config(rcg);
120 }
121 
122 /*
123  * Calculate m/n:d rate
124  *
125  *          parent_rate     m
126  *   rate = ----------- x  ---
127  *            hid_div       n
128  */
129 static unsigned long
130 calc_rate(unsigned long rate, u32 m, u32 n, u32 mode, u32 hid_div)
131 {
132 	if (hid_div) {
133 		rate *= 2;
134 		rate /= hid_div + 1;
135 	}
136 
137 	if (mode) {
138 		u64 tmp = rate;
139 		tmp *= m;
140 		do_div(tmp, n);
141 		rate = tmp;
142 	}
143 
144 	return rate;
145 }
146 
147 static unsigned long
148 clk_rcg2_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
149 {
150 	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
151 	u32 cfg, hid_div, m = 0, n = 0, mode = 0, mask;
152 
153 	regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, &cfg);
154 
155 	if (rcg->mnd_width) {
156 		mask = BIT(rcg->mnd_width) - 1;
157 		regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + M_REG, &m);
158 		m &= mask;
159 		regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + N_REG, &n);
160 		n =  ~n;
161 		n &= mask;
162 		n += m;
163 		mode = cfg & CFG_MODE_MASK;
164 		mode >>= CFG_MODE_SHIFT;
165 	}
166 
167 	mask = BIT(rcg->hid_width) - 1;
168 	hid_div = cfg >> CFG_SRC_DIV_SHIFT;
169 	hid_div &= mask;
170 
171 	return calc_rate(parent_rate, m, n, mode, hid_div);
172 }
173 
174 static const
175 struct freq_tbl *find_freq(const struct freq_tbl *f, unsigned long rate)
176 {
177 	if (!f)
178 		return NULL;
179 
180 	for (; f->freq; f++)
181 		if (rate <= f->freq)
182 			return f;
183 
184 	return NULL;
185 }
186 
187 static long _freq_tbl_determine_rate(struct clk_hw *hw,
188 		const struct freq_tbl *f, unsigned long rate,
189 		unsigned long *p_rate, struct clk **p)
190 {
191 	unsigned long clk_flags;
192 
193 	f = find_freq(f, rate);
194 	if (!f)
195 		return -EINVAL;
196 
197 	clk_flags = __clk_get_flags(hw->clk);
198 	*p = clk_get_parent_by_index(hw->clk, f->src);
199 	if (clk_flags & CLK_SET_RATE_PARENT) {
200 		if (f->pre_div) {
201 			rate /= 2;
202 			rate *= f->pre_div + 1;
203 		}
204 
205 		if (f->n) {
206 			u64 tmp = rate;
207 			tmp = tmp * f->n;
208 			do_div(tmp, f->m);
209 			rate = tmp;
210 		}
211 	} else {
212 		rate =  __clk_get_rate(*p);
213 	}
214 	*p_rate = rate;
215 
216 	return f->freq;
217 }
218 
219 static long clk_rcg2_determine_rate(struct clk_hw *hw, unsigned long rate,
220 		unsigned long *p_rate, struct clk **p)
221 {
222 	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
223 
224 	return _freq_tbl_determine_rate(hw, rcg->freq_tbl, rate, p_rate, p);
225 }
226 
227 static int __clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate)
228 {
229 	struct clk_rcg2 *rcg = to_clk_rcg2(hw);
230 	const struct freq_tbl *f;
231 	u32 cfg, mask;
232 	int ret;
233 
234 	f = find_freq(rcg->freq_tbl, rate);
235 	if (!f)
236 		return -EINVAL;
237 
238 	if (rcg->mnd_width && f->n) {
239 		mask = BIT(rcg->mnd_width) - 1;
240 		ret = regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + M_REG,
241 					 mask, f->m);
242 		if (ret)
243 			return ret;
244 
245 		ret = regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + N_REG,
246 					 mask, ~(f->n - f->m));
247 		if (ret)
248 			return ret;
249 
250 		ret = regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + D_REG,
251 					 mask, ~f->n);
252 		if (ret)
253 			return ret;
254 	}
255 
256 	mask = BIT(rcg->hid_width) - 1;
257 	mask |= CFG_SRC_SEL_MASK | CFG_MODE_MASK;
258 	cfg = f->pre_div << CFG_SRC_DIV_SHIFT;
259 	cfg |= rcg->parent_map[f->src] << CFG_SRC_SEL_SHIFT;
260 	if (rcg->mnd_width && f->n)
261 		cfg |= CFG_MODE_DUAL_EDGE;
262 	ret = regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, mask,
263 			cfg);
264 	if (ret)
265 		return ret;
266 
267 	return update_config(rcg);
268 }
269 
270 static int clk_rcg2_set_rate(struct clk_hw *hw, unsigned long rate,
271 			    unsigned long parent_rate)
272 {
273 	return __clk_rcg2_set_rate(hw, rate);
274 }
275 
276 static int clk_rcg2_set_rate_and_parent(struct clk_hw *hw,
277 		unsigned long rate, unsigned long parent_rate, u8 index)
278 {
279 	return __clk_rcg2_set_rate(hw, rate);
280 }
281 
282 const struct clk_ops clk_rcg2_ops = {
283 	.is_enabled = clk_rcg2_is_enabled,
284 	.get_parent = clk_rcg2_get_parent,
285 	.set_parent = clk_rcg2_set_parent,
286 	.recalc_rate = clk_rcg2_recalc_rate,
287 	.determine_rate = clk_rcg2_determine_rate,
288 	.set_rate = clk_rcg2_set_rate,
289 	.set_rate_and_parent = clk_rcg2_set_rate_and_parent,
290 };
291 EXPORT_SYMBOL_GPL(clk_rcg2_ops);
292