• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * JZ47xx SoCs TCU clocks driver
4  * Copyright (C) 2019 Paul Cercueil <paul@crapouillou.net>
5  */
6 
7 #include <linux/clk.h>
8 #include <linux/clk-provider.h>
9 #include <linux/clockchips.h>
10 #include <linux/mfd/ingenic-tcu.h>
11 #include <linux/mfd/syscon.h>
12 #include <linux/regmap.h>
13 #include <linux/slab.h>
14 #include <linux/syscore_ops.h>
15 
16 #include <dt-bindings/clock/ingenic,tcu.h>
17 
18 /* 8 channels max + watchdog + OST */
19 #define TCU_CLK_COUNT	10
20 
21 #undef pr_fmt
22 #define pr_fmt(fmt) "ingenic-tcu-clk: " fmt
23 
24 enum tcu_clk_parent {
25 	TCU_PARENT_PCLK,
26 	TCU_PARENT_RTC,
27 	TCU_PARENT_EXT,
28 };
29 
30 struct ingenic_soc_info {
31 	unsigned int num_channels;
32 	bool has_ost;
33 	bool has_tcu_clk;
34 };
35 
36 struct ingenic_tcu_clk_info {
37 	struct clk_init_data init_data;
38 	u8 gate_bit;
39 	u8 tcsr_reg;
40 };
41 
42 struct ingenic_tcu_clk {
43 	struct clk_hw hw;
44 	unsigned int idx;
45 	struct ingenic_tcu *tcu;
46 	const struct ingenic_tcu_clk_info *info;
47 };
48 
49 struct ingenic_tcu {
50 	const struct ingenic_soc_info *soc_info;
51 	struct regmap *map;
52 	struct clk *clk;
53 
54 	struct clk_hw_onecell_data *clocks;
55 };
56 
57 static struct ingenic_tcu *ingenic_tcu;
58 
to_tcu_clk(struct clk_hw * hw)59 static inline struct ingenic_tcu_clk *to_tcu_clk(struct clk_hw *hw)
60 {
61 	return container_of(hw, struct ingenic_tcu_clk, hw);
62 }
63 
ingenic_tcu_enable(struct clk_hw * hw)64 static int ingenic_tcu_enable(struct clk_hw *hw)
65 {
66 	struct ingenic_tcu_clk *tcu_clk = to_tcu_clk(hw);
67 	const struct ingenic_tcu_clk_info *info = tcu_clk->info;
68 	struct ingenic_tcu *tcu = tcu_clk->tcu;
69 
70 	regmap_write(tcu->map, TCU_REG_TSCR, BIT(info->gate_bit));
71 
72 	return 0;
73 }
74 
ingenic_tcu_disable(struct clk_hw * hw)75 static void ingenic_tcu_disable(struct clk_hw *hw)
76 {
77 	struct ingenic_tcu_clk *tcu_clk = to_tcu_clk(hw);
78 	const struct ingenic_tcu_clk_info *info = tcu_clk->info;
79 	struct ingenic_tcu *tcu = tcu_clk->tcu;
80 
81 	regmap_write(tcu->map, TCU_REG_TSSR, BIT(info->gate_bit));
82 }
83 
ingenic_tcu_is_enabled(struct clk_hw * hw)84 static int ingenic_tcu_is_enabled(struct clk_hw *hw)
85 {
86 	struct ingenic_tcu_clk *tcu_clk = to_tcu_clk(hw);
87 	const struct ingenic_tcu_clk_info *info = tcu_clk->info;
88 	unsigned int value;
89 
90 	regmap_read(tcu_clk->tcu->map, TCU_REG_TSR, &value);
91 
92 	return !(value & BIT(info->gate_bit));
93 }
94 
ingenic_tcu_enable_regs(struct clk_hw * hw)95 static bool ingenic_tcu_enable_regs(struct clk_hw *hw)
96 {
97 	struct ingenic_tcu_clk *tcu_clk = to_tcu_clk(hw);
98 	const struct ingenic_tcu_clk_info *info = tcu_clk->info;
99 	struct ingenic_tcu *tcu = tcu_clk->tcu;
100 	bool enabled = false;
101 
102 	/*
103 	 * According to the programming manual, a timer channel's registers can
104 	 * only be accessed when the channel's stop bit is clear.
105 	 */
106 	enabled = !!ingenic_tcu_is_enabled(hw);
107 	regmap_write(tcu->map, TCU_REG_TSCR, BIT(info->gate_bit));
108 
109 	return enabled;
110 }
111 
ingenic_tcu_disable_regs(struct clk_hw * hw)112 static void ingenic_tcu_disable_regs(struct clk_hw *hw)
113 {
114 	struct ingenic_tcu_clk *tcu_clk = to_tcu_clk(hw);
115 	const struct ingenic_tcu_clk_info *info = tcu_clk->info;
116 	struct ingenic_tcu *tcu = tcu_clk->tcu;
117 
118 	regmap_write(tcu->map, TCU_REG_TSSR, BIT(info->gate_bit));
119 }
120 
ingenic_tcu_get_parent(struct clk_hw * hw)121 static u8 ingenic_tcu_get_parent(struct clk_hw *hw)
122 {
123 	struct ingenic_tcu_clk *tcu_clk = to_tcu_clk(hw);
124 	const struct ingenic_tcu_clk_info *info = tcu_clk->info;
125 	unsigned int val = 0;
126 	int ret;
127 
128 	ret = regmap_read(tcu_clk->tcu->map, info->tcsr_reg, &val);
129 	WARN_ONCE(ret < 0, "Unable to read TCSR %d", tcu_clk->idx);
130 
131 	return ffs(val & TCU_TCSR_PARENT_CLOCK_MASK) - 1;
132 }
133 
ingenic_tcu_set_parent(struct clk_hw * hw,u8 idx)134 static int ingenic_tcu_set_parent(struct clk_hw *hw, u8 idx)
135 {
136 	struct ingenic_tcu_clk *tcu_clk = to_tcu_clk(hw);
137 	const struct ingenic_tcu_clk_info *info = tcu_clk->info;
138 	bool was_enabled;
139 	int ret;
140 
141 	was_enabled = ingenic_tcu_enable_regs(hw);
142 
143 	ret = regmap_update_bits(tcu_clk->tcu->map, info->tcsr_reg,
144 				 TCU_TCSR_PARENT_CLOCK_MASK, BIT(idx));
145 	WARN_ONCE(ret < 0, "Unable to update TCSR %d", tcu_clk->idx);
146 
147 	if (!was_enabled)
148 		ingenic_tcu_disable_regs(hw);
149 
150 	return 0;
151 }
152 
ingenic_tcu_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)153 static unsigned long ingenic_tcu_recalc_rate(struct clk_hw *hw,
154 		unsigned long parent_rate)
155 {
156 	struct ingenic_tcu_clk *tcu_clk = to_tcu_clk(hw);
157 	const struct ingenic_tcu_clk_info *info = tcu_clk->info;
158 	unsigned int prescale;
159 	int ret;
160 
161 	ret = regmap_read(tcu_clk->tcu->map, info->tcsr_reg, &prescale);
162 	WARN_ONCE(ret < 0, "Unable to read TCSR %d", tcu_clk->idx);
163 
164 	prescale = (prescale & TCU_TCSR_PRESCALE_MASK) >> TCU_TCSR_PRESCALE_LSB;
165 
166 	return parent_rate >> (prescale * 2);
167 }
168 
ingenic_tcu_get_prescale(unsigned long rate,unsigned long req_rate)169 static u8 ingenic_tcu_get_prescale(unsigned long rate, unsigned long req_rate)
170 {
171 	u8 prescale;
172 
173 	for (prescale = 0; prescale < 5; prescale++)
174 		if ((rate >> (prescale * 2)) <= req_rate)
175 			return prescale;
176 
177 	return 5; /* /1024 divider */
178 }
179 
ingenic_tcu_round_rate(struct clk_hw * hw,unsigned long req_rate,unsigned long * parent_rate)180 static long ingenic_tcu_round_rate(struct clk_hw *hw, unsigned long req_rate,
181 		unsigned long *parent_rate)
182 {
183 	unsigned long rate = *parent_rate;
184 	u8 prescale;
185 
186 	if (req_rate > rate)
187 		return rate;
188 
189 	prescale = ingenic_tcu_get_prescale(rate, req_rate);
190 
191 	return rate >> (prescale * 2);
192 }
193 
ingenic_tcu_set_rate(struct clk_hw * hw,unsigned long req_rate,unsigned long parent_rate)194 static int ingenic_tcu_set_rate(struct clk_hw *hw, unsigned long req_rate,
195 		unsigned long parent_rate)
196 {
197 	struct ingenic_tcu_clk *tcu_clk = to_tcu_clk(hw);
198 	const struct ingenic_tcu_clk_info *info = tcu_clk->info;
199 	u8 prescale = ingenic_tcu_get_prescale(parent_rate, req_rate);
200 	bool was_enabled;
201 	int ret;
202 
203 	was_enabled = ingenic_tcu_enable_regs(hw);
204 
205 	ret = regmap_update_bits(tcu_clk->tcu->map, info->tcsr_reg,
206 				 TCU_TCSR_PRESCALE_MASK,
207 				 prescale << TCU_TCSR_PRESCALE_LSB);
208 	WARN_ONCE(ret < 0, "Unable to update TCSR %d", tcu_clk->idx);
209 
210 	if (!was_enabled)
211 		ingenic_tcu_disable_regs(hw);
212 
213 	return 0;
214 }
215 
216 static const struct clk_ops ingenic_tcu_clk_ops = {
217 	.get_parent	= ingenic_tcu_get_parent,
218 	.set_parent	= ingenic_tcu_set_parent,
219 
220 	.recalc_rate	= ingenic_tcu_recalc_rate,
221 	.round_rate	= ingenic_tcu_round_rate,
222 	.set_rate	= ingenic_tcu_set_rate,
223 
224 	.enable		= ingenic_tcu_enable,
225 	.disable	= ingenic_tcu_disable,
226 	.is_enabled	= ingenic_tcu_is_enabled,
227 };
228 
229 static const char * const ingenic_tcu_timer_parents[] = {
230 	[TCU_PARENT_PCLK] = "pclk",
231 	[TCU_PARENT_RTC]  = "rtc",
232 	[TCU_PARENT_EXT]  = "ext",
233 };
234 
235 #define DEF_TIMER(_name, _gate_bit, _tcsr)				\
236 	{								\
237 		.init_data = {						\
238 			.name = _name,					\
239 			.parent_names = ingenic_tcu_timer_parents,	\
240 			.num_parents = ARRAY_SIZE(ingenic_tcu_timer_parents),\
241 			.ops = &ingenic_tcu_clk_ops,			\
242 			.flags = CLK_SET_RATE_UNGATE,			\
243 		},							\
244 		.gate_bit = _gate_bit,					\
245 		.tcsr_reg = _tcsr,					\
246 	}
247 static const struct ingenic_tcu_clk_info ingenic_tcu_clk_info[] = {
248 	[TCU_CLK_TIMER0] = DEF_TIMER("timer0", 0, TCU_REG_TCSRc(0)),
249 	[TCU_CLK_TIMER1] = DEF_TIMER("timer1", 1, TCU_REG_TCSRc(1)),
250 	[TCU_CLK_TIMER2] = DEF_TIMER("timer2", 2, TCU_REG_TCSRc(2)),
251 	[TCU_CLK_TIMER3] = DEF_TIMER("timer3", 3, TCU_REG_TCSRc(3)),
252 	[TCU_CLK_TIMER4] = DEF_TIMER("timer4", 4, TCU_REG_TCSRc(4)),
253 	[TCU_CLK_TIMER5] = DEF_TIMER("timer5", 5, TCU_REG_TCSRc(5)),
254 	[TCU_CLK_TIMER6] = DEF_TIMER("timer6", 6, TCU_REG_TCSRc(6)),
255 	[TCU_CLK_TIMER7] = DEF_TIMER("timer7", 7, TCU_REG_TCSRc(7)),
256 };
257 
258 static const struct ingenic_tcu_clk_info ingenic_tcu_watchdog_clk_info =
259 					 DEF_TIMER("wdt", 16, TCU_REG_WDT_TCSR);
260 static const struct ingenic_tcu_clk_info ingenic_tcu_ost_clk_info =
261 					 DEF_TIMER("ost", 15, TCU_REG_OST_TCSR);
262 #undef DEF_TIMER
263 
ingenic_tcu_register_clock(struct ingenic_tcu * tcu,unsigned int idx,enum tcu_clk_parent parent,const struct ingenic_tcu_clk_info * info,struct clk_hw_onecell_data * clocks)264 static int __init ingenic_tcu_register_clock(struct ingenic_tcu *tcu,
265 			unsigned int idx, enum tcu_clk_parent parent,
266 			const struct ingenic_tcu_clk_info *info,
267 			struct clk_hw_onecell_data *clocks)
268 {
269 	struct ingenic_tcu_clk *tcu_clk;
270 	int err;
271 
272 	tcu_clk = kzalloc(sizeof(*tcu_clk), GFP_KERNEL);
273 	if (!tcu_clk)
274 		return -ENOMEM;
275 
276 	tcu_clk->hw.init = &info->init_data;
277 	tcu_clk->idx = idx;
278 	tcu_clk->info = info;
279 	tcu_clk->tcu = tcu;
280 
281 	/* Reset channel and clock divider, set default parent */
282 	ingenic_tcu_enable_regs(&tcu_clk->hw);
283 	regmap_update_bits(tcu->map, info->tcsr_reg, 0xffff, BIT(parent));
284 	ingenic_tcu_disable_regs(&tcu_clk->hw);
285 
286 	err = clk_hw_register(NULL, &tcu_clk->hw);
287 	if (err) {
288 		kfree(tcu_clk);
289 		return err;
290 	}
291 
292 	clocks->hws[idx] = &tcu_clk->hw;
293 
294 	return 0;
295 }
296 
297 static const struct ingenic_soc_info jz4740_soc_info = {
298 	.num_channels = 8,
299 	.has_ost = false,
300 	.has_tcu_clk = true,
301 };
302 
303 static const struct ingenic_soc_info jz4725b_soc_info = {
304 	.num_channels = 6,
305 	.has_ost = true,
306 	.has_tcu_clk = true,
307 };
308 
309 static const struct ingenic_soc_info jz4770_soc_info = {
310 	.num_channels = 8,
311 	.has_ost = true,
312 	.has_tcu_clk = false,
313 };
314 
315 static const struct ingenic_soc_info x1000_soc_info = {
316 	.num_channels = 8,
317 	.has_ost = false, /* X1000 has OST, but it not belong TCU */
318 	.has_tcu_clk = false,
319 };
320 
321 static const struct of_device_id __maybe_unused ingenic_tcu_of_match[] __initconst = {
322 	{ .compatible = "ingenic,jz4740-tcu", .data = &jz4740_soc_info, },
323 	{ .compatible = "ingenic,jz4725b-tcu", .data = &jz4725b_soc_info, },
324 	{ .compatible = "ingenic,jz4770-tcu", .data = &jz4770_soc_info, },
325 	{ .compatible = "ingenic,x1000-tcu", .data = &x1000_soc_info, },
326 	{ /* sentinel */ }
327 };
328 
ingenic_tcu_probe(struct device_node * np)329 static int __init ingenic_tcu_probe(struct device_node *np)
330 {
331 	const struct of_device_id *id = of_match_node(ingenic_tcu_of_match, np);
332 	struct ingenic_tcu *tcu;
333 	struct regmap *map;
334 	unsigned int i;
335 	int ret;
336 
337 	map = device_node_to_regmap(np);
338 	if (IS_ERR(map))
339 		return PTR_ERR(map);
340 
341 	tcu = kzalloc(sizeof(*tcu), GFP_KERNEL);
342 	if (!tcu)
343 		return -ENOMEM;
344 
345 	tcu->map = map;
346 	tcu->soc_info = id->data;
347 
348 	if (tcu->soc_info->has_tcu_clk) {
349 		tcu->clk = of_clk_get_by_name(np, "tcu");
350 		if (IS_ERR(tcu->clk)) {
351 			ret = PTR_ERR(tcu->clk);
352 			pr_crit("Cannot get TCU clock\n");
353 			goto err_free_tcu;
354 		}
355 
356 		ret = clk_prepare_enable(tcu->clk);
357 		if (ret) {
358 			pr_crit("Unable to enable TCU clock\n");
359 			goto err_put_clk;
360 		}
361 	}
362 
363 	tcu->clocks = kzalloc(struct_size(tcu->clocks, hws, TCU_CLK_COUNT),
364 			      GFP_KERNEL);
365 	if (!tcu->clocks) {
366 		ret = -ENOMEM;
367 		goto err_clk_disable;
368 	}
369 
370 	tcu->clocks->num = TCU_CLK_COUNT;
371 
372 	for (i = 0; i < tcu->soc_info->num_channels; i++) {
373 		ret = ingenic_tcu_register_clock(tcu, i, TCU_PARENT_EXT,
374 						 &ingenic_tcu_clk_info[i],
375 						 tcu->clocks);
376 		if (ret) {
377 			pr_crit("cannot register clock %d\n", i);
378 			goto err_unregister_timer_clocks;
379 		}
380 	}
381 
382 	/*
383 	 * We set EXT as the default parent clock for all the TCU clocks
384 	 * except for the watchdog one, where we set the RTC clock as the
385 	 * parent. Since the EXT and PCLK are much faster than the RTC clock,
386 	 * the watchdog would kick after a maximum time of 5s, and we might
387 	 * want a slower kicking time.
388 	 */
389 	ret = ingenic_tcu_register_clock(tcu, TCU_CLK_WDT, TCU_PARENT_RTC,
390 					 &ingenic_tcu_watchdog_clk_info,
391 					 tcu->clocks);
392 	if (ret) {
393 		pr_crit("cannot register watchdog clock\n");
394 		goto err_unregister_timer_clocks;
395 	}
396 
397 	if (tcu->soc_info->has_ost) {
398 		ret = ingenic_tcu_register_clock(tcu, TCU_CLK_OST,
399 						 TCU_PARENT_EXT,
400 						 &ingenic_tcu_ost_clk_info,
401 						 tcu->clocks);
402 		if (ret) {
403 			pr_crit("cannot register ost clock\n");
404 			goto err_unregister_watchdog_clock;
405 		}
406 	}
407 
408 	ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, tcu->clocks);
409 	if (ret) {
410 		pr_crit("cannot add OF clock provider\n");
411 		goto err_unregister_ost_clock;
412 	}
413 
414 	ingenic_tcu = tcu;
415 
416 	return 0;
417 
418 err_unregister_ost_clock:
419 	if (tcu->soc_info->has_ost)
420 		clk_hw_unregister(tcu->clocks->hws[i + 1]);
421 err_unregister_watchdog_clock:
422 	clk_hw_unregister(tcu->clocks->hws[i]);
423 err_unregister_timer_clocks:
424 	for (i = 0; i < tcu->clocks->num; i++)
425 		if (tcu->clocks->hws[i])
426 			clk_hw_unregister(tcu->clocks->hws[i]);
427 	kfree(tcu->clocks);
428 err_clk_disable:
429 	if (tcu->soc_info->has_tcu_clk)
430 		clk_disable_unprepare(tcu->clk);
431 err_put_clk:
432 	if (tcu->soc_info->has_tcu_clk)
433 		clk_put(tcu->clk);
434 err_free_tcu:
435 	kfree(tcu);
436 	return ret;
437 }
438 
tcu_pm_suspend(void)439 static int __maybe_unused tcu_pm_suspend(void)
440 {
441 	struct ingenic_tcu *tcu = ingenic_tcu;
442 
443 	if (tcu->clk)
444 		clk_disable(tcu->clk);
445 
446 	return 0;
447 }
448 
tcu_pm_resume(void)449 static void __maybe_unused tcu_pm_resume(void)
450 {
451 	struct ingenic_tcu *tcu = ingenic_tcu;
452 
453 	if (tcu->clk)
454 		clk_enable(tcu->clk);
455 }
456 
457 static struct syscore_ops __maybe_unused tcu_pm_ops = {
458 	.suspend = tcu_pm_suspend,
459 	.resume = tcu_pm_resume,
460 };
461 
ingenic_tcu_init(struct device_node * np)462 static void __init ingenic_tcu_init(struct device_node *np)
463 {
464 	int ret = ingenic_tcu_probe(np);
465 
466 	if (ret)
467 		pr_crit("Failed to initialize TCU clocks: %d\n", ret);
468 
469 	if (IS_ENABLED(CONFIG_PM_SLEEP))
470 		register_syscore_ops(&tcu_pm_ops);
471 }
472 
473 CLK_OF_DECLARE_DRIVER(jz4740_cgu, "ingenic,jz4740-tcu", ingenic_tcu_init);
474 CLK_OF_DECLARE_DRIVER(jz4725b_cgu, "ingenic,jz4725b-tcu", ingenic_tcu_init);
475 CLK_OF_DECLARE_DRIVER(jz4770_cgu, "ingenic,jz4770-tcu", ingenic_tcu_init);
476 CLK_OF_DECLARE_DRIVER(x1000_cgu, "ingenic,x1000-tcu", ingenic_tcu_init);
477