1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * drivers/clk/at91/sckc.c
4 *
5 *  Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
6 */
7
8#include <linux/clk-provider.h>
9#include <linux/clkdev.h>
10#include <linux/delay.h>
11#include <linux/of.h>
12#include <linux/of_address.h>
13#include <linux/io.h>
14
15#define SLOW_CLOCK_FREQ		32768
16#define SLOWCK_SW_CYCLES	5
17#define SLOWCK_SW_TIME_USEC	((SLOWCK_SW_CYCLES * USEC_PER_SEC) / \
18				 SLOW_CLOCK_FREQ)
19
20#define	AT91_SCKC_CR			0x00
21
22struct clk_slow_bits {
23	u32 cr_rcen;
24	u32 cr_osc32en;
25	u32 cr_osc32byp;
26	u32 cr_oscsel;
27};
28
29struct clk_slow_osc {
30	struct clk_hw hw;
31	void __iomem *sckcr;
32	const struct clk_slow_bits *bits;
33	unsigned long startup_usec;
34};
35
36#define to_clk_slow_osc(hw) container_of(hw, struct clk_slow_osc, hw)
37
38struct clk_sama5d4_slow_osc {
39	struct clk_hw hw;
40	void __iomem *sckcr;
41	const struct clk_slow_bits *bits;
42	unsigned long startup_usec;
43	bool prepared;
44};
45
46#define to_clk_sama5d4_slow_osc(hw) container_of(hw, struct clk_sama5d4_slow_osc, hw)
47
48struct clk_slow_rc_osc {
49	struct clk_hw hw;
50	void __iomem *sckcr;
51	const struct clk_slow_bits *bits;
52	unsigned long frequency;
53	unsigned long accuracy;
54	unsigned long startup_usec;
55};
56
57#define to_clk_slow_rc_osc(hw) container_of(hw, struct clk_slow_rc_osc, hw)
58
59struct clk_sam9x5_slow {
60	struct clk_hw hw;
61	void __iomem *sckcr;
62	const struct clk_slow_bits *bits;
63	u8 parent;
64};
65
66#define to_clk_sam9x5_slow(hw) container_of(hw, struct clk_sam9x5_slow, hw)
67
68static int clk_slow_osc_prepare(struct clk_hw *hw)
69{
70	struct clk_slow_osc *osc = to_clk_slow_osc(hw);
71	void __iomem *sckcr = osc->sckcr;
72	u32 tmp = readl(sckcr);
73
74	if (tmp & (osc->bits->cr_osc32byp | osc->bits->cr_osc32en))
75		return 0;
76
77	writel(tmp | osc->bits->cr_osc32en, sckcr);
78
79	if (system_state < SYSTEM_RUNNING)
80		udelay(osc->startup_usec);
81	else
82		usleep_range(osc->startup_usec, osc->startup_usec + 1);
83
84	return 0;
85}
86
87static void clk_slow_osc_unprepare(struct clk_hw *hw)
88{
89	struct clk_slow_osc *osc = to_clk_slow_osc(hw);
90	void __iomem *sckcr = osc->sckcr;
91	u32 tmp = readl(sckcr);
92
93	if (tmp & osc->bits->cr_osc32byp)
94		return;
95
96	writel(tmp & ~osc->bits->cr_osc32en, sckcr);
97}
98
99static int clk_slow_osc_is_prepared(struct clk_hw *hw)
100{
101	struct clk_slow_osc *osc = to_clk_slow_osc(hw);
102	void __iomem *sckcr = osc->sckcr;
103	u32 tmp = readl(sckcr);
104
105	if (tmp & osc->bits->cr_osc32byp)
106		return 1;
107
108	return !!(tmp & osc->bits->cr_osc32en);
109}
110
111static const struct clk_ops slow_osc_ops = {
112	.prepare = clk_slow_osc_prepare,
113	.unprepare = clk_slow_osc_unprepare,
114	.is_prepared = clk_slow_osc_is_prepared,
115};
116
117static struct clk_hw * __init
118at91_clk_register_slow_osc(void __iomem *sckcr,
119			   const char *name,
120			   const struct clk_parent_data *parent_data,
121			   unsigned long startup,
122			   bool bypass,
123			   const struct clk_slow_bits *bits)
124{
125	struct clk_slow_osc *osc;
126	struct clk_hw *hw;
127	struct clk_init_data init = {};
128	int ret;
129
130	if (!sckcr || !name || !parent_data)
131		return ERR_PTR(-EINVAL);
132
133	osc = kzalloc(sizeof(*osc), GFP_KERNEL);
134	if (!osc)
135		return ERR_PTR(-ENOMEM);
136
137	init.name = name;
138	init.ops = &slow_osc_ops;
139	init.parent_data = parent_data;
140	init.num_parents = 1;
141	init.flags = CLK_IGNORE_UNUSED;
142
143	osc->hw.init = &init;
144	osc->sckcr = sckcr;
145	osc->startup_usec = startup;
146	osc->bits = bits;
147
148	if (bypass)
149		writel((readl(sckcr) & ~osc->bits->cr_osc32en) |
150					osc->bits->cr_osc32byp, sckcr);
151
152	hw = &osc->hw;
153	ret = clk_hw_register(NULL, &osc->hw);
154	if (ret) {
155		kfree(osc);
156		hw = ERR_PTR(ret);
157	}
158
159	return hw;
160}
161
162static void at91_clk_unregister_slow_osc(struct clk_hw *hw)
163{
164	struct clk_slow_osc *osc = to_clk_slow_osc(hw);
165
166	clk_hw_unregister(hw);
167	kfree(osc);
168}
169
170static unsigned long clk_slow_rc_osc_recalc_rate(struct clk_hw *hw,
171						 unsigned long parent_rate)
172{
173	struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw);
174
175	return osc->frequency;
176}
177
178static unsigned long clk_slow_rc_osc_recalc_accuracy(struct clk_hw *hw,
179						     unsigned long parent_acc)
180{
181	struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw);
182
183	return osc->accuracy;
184}
185
186static int clk_slow_rc_osc_prepare(struct clk_hw *hw)
187{
188	struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw);
189	void __iomem *sckcr = osc->sckcr;
190
191	writel(readl(sckcr) | osc->bits->cr_rcen, sckcr);
192
193	if (system_state < SYSTEM_RUNNING)
194		udelay(osc->startup_usec);
195	else
196		usleep_range(osc->startup_usec, osc->startup_usec + 1);
197
198	return 0;
199}
200
201static void clk_slow_rc_osc_unprepare(struct clk_hw *hw)
202{
203	struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw);
204	void __iomem *sckcr = osc->sckcr;
205
206	writel(readl(sckcr) & ~osc->bits->cr_rcen, sckcr);
207}
208
209static int clk_slow_rc_osc_is_prepared(struct clk_hw *hw)
210{
211	struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw);
212
213	return !!(readl(osc->sckcr) & osc->bits->cr_rcen);
214}
215
216static const struct clk_ops slow_rc_osc_ops = {
217	.prepare = clk_slow_rc_osc_prepare,
218	.unprepare = clk_slow_rc_osc_unprepare,
219	.is_prepared = clk_slow_rc_osc_is_prepared,
220	.recalc_rate = clk_slow_rc_osc_recalc_rate,
221	.recalc_accuracy = clk_slow_rc_osc_recalc_accuracy,
222};
223
224static struct clk_hw * __init
225at91_clk_register_slow_rc_osc(void __iomem *sckcr,
226			      const char *name,
227			      unsigned long frequency,
228			      unsigned long accuracy,
229			      unsigned long startup,
230			      const struct clk_slow_bits *bits)
231{
232	struct clk_slow_rc_osc *osc;
233	struct clk_hw *hw;
234	struct clk_init_data init;
235	int ret;
236
237	if (!sckcr || !name)
238		return ERR_PTR(-EINVAL);
239
240	osc = kzalloc(sizeof(*osc), GFP_KERNEL);
241	if (!osc)
242		return ERR_PTR(-ENOMEM);
243
244	init.name = name;
245	init.ops = &slow_rc_osc_ops;
246	init.parent_names = NULL;
247	init.num_parents = 0;
248	init.flags = CLK_IGNORE_UNUSED;
249
250	osc->hw.init = &init;
251	osc->sckcr = sckcr;
252	osc->bits = bits;
253	osc->frequency = frequency;
254	osc->accuracy = accuracy;
255	osc->startup_usec = startup;
256
257	hw = &osc->hw;
258	ret = clk_hw_register(NULL, &osc->hw);
259	if (ret) {
260		kfree(osc);
261		hw = ERR_PTR(ret);
262	}
263
264	return hw;
265}
266
267static void at91_clk_unregister_slow_rc_osc(struct clk_hw *hw)
268{
269	struct clk_slow_rc_osc *osc = to_clk_slow_rc_osc(hw);
270
271	clk_hw_unregister(hw);
272	kfree(osc);
273}
274
275static int clk_sam9x5_slow_set_parent(struct clk_hw *hw, u8 index)
276{
277	struct clk_sam9x5_slow *slowck = to_clk_sam9x5_slow(hw);
278	void __iomem *sckcr = slowck->sckcr;
279	u32 tmp;
280
281	if (index > 1)
282		return -EINVAL;
283
284	tmp = readl(sckcr);
285
286	if ((!index && !(tmp & slowck->bits->cr_oscsel)) ||
287	    (index && (tmp & slowck->bits->cr_oscsel)))
288		return 0;
289
290	if (index)
291		tmp |= slowck->bits->cr_oscsel;
292	else
293		tmp &= ~slowck->bits->cr_oscsel;
294
295	writel(tmp, sckcr);
296
297	if (system_state < SYSTEM_RUNNING)
298		udelay(SLOWCK_SW_TIME_USEC);
299	else
300		usleep_range(SLOWCK_SW_TIME_USEC, SLOWCK_SW_TIME_USEC + 1);
301
302	return 0;
303}
304
305static u8 clk_sam9x5_slow_get_parent(struct clk_hw *hw)
306{
307	struct clk_sam9x5_slow *slowck = to_clk_sam9x5_slow(hw);
308
309	return !!(readl(slowck->sckcr) & slowck->bits->cr_oscsel);
310}
311
312static const struct clk_ops sam9x5_slow_ops = {
313	.determine_rate = clk_hw_determine_rate_no_reparent,
314	.set_parent = clk_sam9x5_slow_set_parent,
315	.get_parent = clk_sam9x5_slow_get_parent,
316};
317
318static struct clk_hw * __init
319at91_clk_register_sam9x5_slow(void __iomem *sckcr,
320			      const char *name,
321			      const struct clk_hw **parent_hws,
322			      int num_parents,
323			      const struct clk_slow_bits *bits)
324{
325	struct clk_sam9x5_slow *slowck;
326	struct clk_hw *hw;
327	struct clk_init_data init = {};
328	int ret;
329
330	if (!sckcr || !name || !parent_hws || !num_parents)
331		return ERR_PTR(-EINVAL);
332
333	slowck = kzalloc(sizeof(*slowck), GFP_KERNEL);
334	if (!slowck)
335		return ERR_PTR(-ENOMEM);
336
337	init.name = name;
338	init.ops = &sam9x5_slow_ops;
339	init.parent_hws = parent_hws;
340	init.num_parents = num_parents;
341	init.flags = 0;
342
343	slowck->hw.init = &init;
344	slowck->sckcr = sckcr;
345	slowck->bits = bits;
346	slowck->parent = !!(readl(sckcr) & slowck->bits->cr_oscsel);
347
348	hw = &slowck->hw;
349	ret = clk_hw_register(NULL, &slowck->hw);
350	if (ret) {
351		kfree(slowck);
352		hw = ERR_PTR(ret);
353	}
354
355	return hw;
356}
357
358static void at91_clk_unregister_sam9x5_slow(struct clk_hw *hw)
359{
360	struct clk_sam9x5_slow *slowck = to_clk_sam9x5_slow(hw);
361
362	clk_hw_unregister(hw);
363	kfree(slowck);
364}
365
366static void __init at91sam9x5_sckc_register(struct device_node *np,
367					    unsigned int rc_osc_startup_us,
368					    const struct clk_slow_bits *bits)
369{
370	void __iomem *regbase = of_iomap(np, 0);
371	struct device_node *child = NULL;
372	const char *xtal_name;
373	struct clk_hw *slow_rc, *slow_osc, *slowck;
374	static struct clk_parent_data parent_data = {
375		.name = "slow_xtal",
376	};
377	const struct clk_hw *parent_hws[2];
378	bool bypass;
379	int ret;
380
381	if (!regbase)
382		return;
383
384	slow_rc = at91_clk_register_slow_rc_osc(regbase, "slow_rc_osc",
385						32768, 50000000,
386						rc_osc_startup_us, bits);
387	if (IS_ERR(slow_rc))
388		return;
389
390	xtal_name = of_clk_get_parent_name(np, 0);
391	if (!xtal_name) {
392		/* DT backward compatibility */
393		child = of_get_compatible_child(np, "atmel,at91sam9x5-clk-slow-osc");
394		if (!child)
395			goto unregister_slow_rc;
396
397		xtal_name = of_clk_get_parent_name(child, 0);
398		bypass = of_property_read_bool(child, "atmel,osc-bypass");
399
400		child =  of_get_compatible_child(np, "atmel,at91sam9x5-clk-slow");
401	} else {
402		bypass = of_property_read_bool(np, "atmel,osc-bypass");
403	}
404
405	if (!xtal_name)
406		goto unregister_slow_rc;
407
408	parent_data.fw_name = xtal_name;
409
410	slow_osc = at91_clk_register_slow_osc(regbase, "slow_osc",
411					      &parent_data, 1200000, bypass, bits);
412	if (IS_ERR(slow_osc))
413		goto unregister_slow_rc;
414
415	parent_hws[0] = slow_rc;
416	parent_hws[1] = slow_osc;
417	slowck = at91_clk_register_sam9x5_slow(regbase, "slowck", parent_hws,
418					       2, bits);
419	if (IS_ERR(slowck))
420		goto unregister_slow_osc;
421
422	/* DT backward compatibility */
423	if (child)
424		ret = of_clk_add_hw_provider(child, of_clk_hw_simple_get,
425					     slowck);
426	else
427		ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get, slowck);
428
429	if (WARN_ON(ret))
430		goto unregister_slowck;
431
432	return;
433
434unregister_slowck:
435	at91_clk_unregister_sam9x5_slow(slowck);
436unregister_slow_osc:
437	at91_clk_unregister_slow_osc(slow_osc);
438unregister_slow_rc:
439	at91_clk_unregister_slow_rc_osc(slow_rc);
440}
441
442static const struct clk_slow_bits at91sam9x5_bits = {
443	.cr_rcen = BIT(0),
444	.cr_osc32en = BIT(1),
445	.cr_osc32byp = BIT(2),
446	.cr_oscsel = BIT(3),
447};
448
449static void __init of_at91sam9x5_sckc_setup(struct device_node *np)
450{
451	at91sam9x5_sckc_register(np, 75, &at91sam9x5_bits);
452}
453CLK_OF_DECLARE(at91sam9x5_clk_sckc, "atmel,at91sam9x5-sckc",
454	       of_at91sam9x5_sckc_setup);
455
456static void __init of_sama5d3_sckc_setup(struct device_node *np)
457{
458	at91sam9x5_sckc_register(np, 500, &at91sam9x5_bits);
459}
460CLK_OF_DECLARE(sama5d3_clk_sckc, "atmel,sama5d3-sckc",
461	       of_sama5d3_sckc_setup);
462
463static const struct clk_slow_bits at91sam9x60_bits = {
464	.cr_osc32en = BIT(1),
465	.cr_osc32byp = BIT(2),
466	.cr_oscsel = BIT(24),
467};
468
469static void __init of_sam9x60_sckc_setup(struct device_node *np)
470{
471	void __iomem *regbase = of_iomap(np, 0);
472	struct clk_hw_onecell_data *clk_data;
473	struct clk_hw *slow_rc, *slow_osc;
474	const char *xtal_name;
475	const struct clk_hw *parent_hws[2];
476	static struct clk_parent_data parent_data = {
477		.name = "slow_xtal",
478	};
479	bool bypass;
480	int ret;
481
482	if (!regbase)
483		return;
484
485	slow_rc = clk_hw_register_fixed_rate_with_accuracy(NULL, "slow_rc_osc",
486							   NULL, 0, 32768,
487							   93750000);
488	if (IS_ERR(slow_rc))
489		return;
490
491	xtal_name = of_clk_get_parent_name(np, 0);
492	if (!xtal_name)
493		goto unregister_slow_rc;
494
495	parent_data.fw_name = xtal_name;
496	bypass = of_property_read_bool(np, "atmel,osc-bypass");
497	slow_osc = at91_clk_register_slow_osc(regbase, "slow_osc",
498					      &parent_data, 5000000, bypass,
499					      &at91sam9x60_bits);
500	if (IS_ERR(slow_osc))
501		goto unregister_slow_rc;
502
503	clk_data = kzalloc(struct_size(clk_data, hws, 2), GFP_KERNEL);
504	if (!clk_data)
505		goto unregister_slow_osc;
506
507	/* MD_SLCK and TD_SLCK. */
508	clk_data->num = 2;
509	clk_data->hws[0] = clk_hw_register_fixed_rate_parent_hw(NULL, "md_slck",
510								slow_rc,
511								0, 32768);
512	if (IS_ERR(clk_data->hws[0]))
513		goto clk_data_free;
514
515	parent_hws[0] = slow_rc;
516	parent_hws[1] = slow_osc;
517	clk_data->hws[1] = at91_clk_register_sam9x5_slow(regbase, "td_slck",
518							 parent_hws, 2,
519							 &at91sam9x60_bits);
520	if (IS_ERR(clk_data->hws[1]))
521		goto unregister_md_slck;
522
523	ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_data);
524	if (WARN_ON(ret))
525		goto unregister_td_slck;
526
527	return;
528
529unregister_td_slck:
530	at91_clk_unregister_sam9x5_slow(clk_data->hws[1]);
531unregister_md_slck:
532	clk_hw_unregister(clk_data->hws[0]);
533clk_data_free:
534	kfree(clk_data);
535unregister_slow_osc:
536	at91_clk_unregister_slow_osc(slow_osc);
537unregister_slow_rc:
538	clk_hw_unregister(slow_rc);
539}
540CLK_OF_DECLARE(sam9x60_clk_sckc, "microchip,sam9x60-sckc",
541	       of_sam9x60_sckc_setup);
542
543static int clk_sama5d4_slow_osc_prepare(struct clk_hw *hw)
544{
545	struct clk_sama5d4_slow_osc *osc = to_clk_sama5d4_slow_osc(hw);
546
547	if (osc->prepared)
548		return 0;
549
550	/*
551	 * Assume that if it has already been selected (for example by the
552	 * bootloader), enough time has already passed.
553	 */
554	if ((readl(osc->sckcr) & osc->bits->cr_oscsel)) {
555		osc->prepared = true;
556		return 0;
557	}
558
559	if (system_state < SYSTEM_RUNNING)
560		udelay(osc->startup_usec);
561	else
562		usleep_range(osc->startup_usec, osc->startup_usec + 1);
563	osc->prepared = true;
564
565	return 0;
566}
567
568static int clk_sama5d4_slow_osc_is_prepared(struct clk_hw *hw)
569{
570	struct clk_sama5d4_slow_osc *osc = to_clk_sama5d4_slow_osc(hw);
571
572	return osc->prepared;
573}
574
575static const struct clk_ops sama5d4_slow_osc_ops = {
576	.prepare = clk_sama5d4_slow_osc_prepare,
577	.is_prepared = clk_sama5d4_slow_osc_is_prepared,
578};
579
580static const struct clk_slow_bits at91sama5d4_bits = {
581	.cr_oscsel = BIT(3),
582};
583
584static void __init of_sama5d4_sckc_setup(struct device_node *np)
585{
586	void __iomem *regbase = of_iomap(np, 0);
587	struct clk_hw *slow_rc, *slowck;
588	struct clk_sama5d4_slow_osc *osc;
589	struct clk_init_data init = {};
590	const char *xtal_name;
591	const struct clk_hw *parent_hws[2];
592	static struct clk_parent_data parent_data = {
593		.name = "slow_xtal",
594	};
595	int ret;
596
597	if (!regbase)
598		return;
599
600	slow_rc = clk_hw_register_fixed_rate_with_accuracy(NULL,
601							   "slow_rc_osc",
602							   NULL, 0, 32768,
603							   250000000);
604	if (IS_ERR(slow_rc))
605		return;
606
607	xtal_name = of_clk_get_parent_name(np, 0);
608	if (!xtal_name)
609		goto unregister_slow_rc;
610	parent_data.fw_name = xtal_name;
611
612	osc = kzalloc(sizeof(*osc), GFP_KERNEL);
613	if (!osc)
614		goto unregister_slow_rc;
615
616	init.name = "slow_osc";
617	init.ops = &sama5d4_slow_osc_ops;
618	init.parent_data = &parent_data;
619	init.num_parents = 1;
620	init.flags = CLK_IGNORE_UNUSED;
621
622	osc->hw.init = &init;
623	osc->sckcr = regbase;
624	osc->startup_usec = 1200000;
625	osc->bits = &at91sama5d4_bits;
626
627	ret = clk_hw_register(NULL, &osc->hw);
628	if (ret)
629		goto free_slow_osc_data;
630
631	parent_hws[0] = slow_rc;
632	parent_hws[1] = &osc->hw;
633	slowck = at91_clk_register_sam9x5_slow(regbase, "slowck",
634					       parent_hws, 2,
635					       &at91sama5d4_bits);
636	if (IS_ERR(slowck))
637		goto unregister_slow_osc;
638
639	ret = of_clk_add_hw_provider(np, of_clk_hw_simple_get, slowck);
640	if (WARN_ON(ret))
641		goto unregister_slowck;
642
643	return;
644
645unregister_slowck:
646	at91_clk_unregister_sam9x5_slow(slowck);
647unregister_slow_osc:
648	clk_hw_unregister(&osc->hw);
649free_slow_osc_data:
650	kfree(osc);
651unregister_slow_rc:
652	clk_hw_unregister(slow_rc);
653}
654CLK_OF_DECLARE(sama5d4_clk_sckc, "atmel,sama5d4-sckc",
655	       of_sama5d4_sckc_setup);
656