Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.5.6.
  1// SPDX-License-Identifier: GPL-2.0-or-later
  2/*
  3 *  Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com>
  4 */
  5
  6#include <linux/clk-provider.h>
  7#include <linux/clkdev.h>
  8#include <linux/clk/at91_pmc.h>
  9#include <linux/delay.h>
 10#include <linux/mfd/syscon.h>
 11#include <linux/regmap.h>
 12
 13#include "pmc.h"
 14
 15#define SLOW_CLOCK_FREQ		32768
 16#define MAINF_DIV		16
 17#define MAINFRDY_TIMEOUT	(((MAINF_DIV + 1) * USEC_PER_SEC) / \
 18				 SLOW_CLOCK_FREQ)
 19#define MAINF_LOOP_MIN_WAIT	(USEC_PER_SEC / SLOW_CLOCK_FREQ)
 20#define MAINF_LOOP_MAX_WAIT	MAINFRDY_TIMEOUT
 21
 22#define MOR_KEY_MASK		(0xff << 16)
 23
 24#define clk_main_parent_select(s)	(((s) & \
 25					(AT91_PMC_MOSCEN | \
 26					AT91_PMC_OSCBYPASS)) ? 1 : 0)
 27
 28struct clk_main_osc {
 29	struct clk_hw hw;
 30	struct regmap *regmap;
 31};
 32
 33#define to_clk_main_osc(hw) container_of(hw, struct clk_main_osc, hw)
 34
 35struct clk_main_rc_osc {
 36	struct clk_hw hw;
 37	struct regmap *regmap;
 38	unsigned long frequency;
 39	unsigned long accuracy;
 40};
 41
 42#define to_clk_main_rc_osc(hw) container_of(hw, struct clk_main_rc_osc, hw)
 43
 44struct clk_rm9200_main {
 45	struct clk_hw hw;
 46	struct regmap *regmap;
 47};
 48
 49#define to_clk_rm9200_main(hw) container_of(hw, struct clk_rm9200_main, hw)
 50
 51struct clk_sam9x5_main {
 52	struct clk_hw hw;
 53	struct regmap *regmap;
 54	u8 parent;
 55};
 56
 57#define to_clk_sam9x5_main(hw) container_of(hw, struct clk_sam9x5_main, hw)
 58
 59static inline bool clk_main_osc_ready(struct regmap *regmap)
 60{
 61	unsigned int status;
 62
 63	regmap_read(regmap, AT91_PMC_SR, &status);
 64
 65	return status & AT91_PMC_MOSCS;
 66}
 67
 68static int clk_main_osc_prepare(struct clk_hw *hw)
 69{
 70	struct clk_main_osc *osc = to_clk_main_osc(hw);
 71	struct regmap *regmap = osc->regmap;
 72	u32 tmp;
 73
 74	regmap_read(regmap, AT91_CKGR_MOR, &tmp);
 75	tmp &= ~MOR_KEY_MASK;
 76
 77	if (tmp & AT91_PMC_OSCBYPASS)
 78		return 0;
 79
 80	if (!(tmp & AT91_PMC_MOSCEN)) {
 81		tmp |= AT91_PMC_MOSCEN | AT91_PMC_KEY;
 82		regmap_write(regmap, AT91_CKGR_MOR, tmp);
 83	}
 84
 85	while (!clk_main_osc_ready(regmap))
 86		cpu_relax();
 87
 88	return 0;
 89}
 90
 91static void clk_main_osc_unprepare(struct clk_hw *hw)
 92{
 93	struct clk_main_osc *osc = to_clk_main_osc(hw);
 94	struct regmap *regmap = osc->regmap;
 95	u32 tmp;
 96
 97	regmap_read(regmap, AT91_CKGR_MOR, &tmp);
 98	if (tmp & AT91_PMC_OSCBYPASS)
 99		return;
100
101	if (!(tmp & AT91_PMC_MOSCEN))
102		return;
103
104	tmp &= ~(AT91_PMC_KEY | AT91_PMC_MOSCEN);
105	regmap_write(regmap, AT91_CKGR_MOR, tmp | AT91_PMC_KEY);
106}
107
108static int clk_main_osc_is_prepared(struct clk_hw *hw)
109{
110	struct clk_main_osc *osc = to_clk_main_osc(hw);
111	struct regmap *regmap = osc->regmap;
112	u32 tmp, status;
113
114	regmap_read(regmap, AT91_CKGR_MOR, &tmp);
115	if (tmp & AT91_PMC_OSCBYPASS)
116		return 1;
117
118	regmap_read(regmap, AT91_PMC_SR, &status);
119
120	return (status & AT91_PMC_MOSCS) && clk_main_parent_select(tmp);
121}
122
123static const struct clk_ops main_osc_ops = {
124	.prepare = clk_main_osc_prepare,
125	.unprepare = clk_main_osc_unprepare,
126	.is_prepared = clk_main_osc_is_prepared,
127};
128
129struct clk_hw * __init
130at91_clk_register_main_osc(struct regmap *regmap,
131			   const char *name,
132			   const char *parent_name,
133			   bool bypass)
134{
135	struct clk_main_osc *osc;
136	struct clk_init_data init;
137	struct clk_hw *hw;
138	int ret;
139
140	if (!name || !parent_name)
141		return ERR_PTR(-EINVAL);
142
143	osc = kzalloc(sizeof(*osc), GFP_KERNEL);
144	if (!osc)
145		return ERR_PTR(-ENOMEM);
146
147	init.name = name;
148	init.ops = &main_osc_ops;
149	init.parent_names = &parent_name;
150	init.num_parents = 1;
151	init.flags = CLK_IGNORE_UNUSED;
152
153	osc->hw.init = &init;
154	osc->regmap = regmap;
155
156	if (bypass)
157		regmap_update_bits(regmap,
158				   AT91_CKGR_MOR, MOR_KEY_MASK |
159				   AT91_PMC_OSCBYPASS,
160				   AT91_PMC_OSCBYPASS | AT91_PMC_KEY);
161
162	hw = &osc->hw;
163	ret = clk_hw_register(NULL, &osc->hw);
164	if (ret) {
165		kfree(osc);
166		hw = ERR_PTR(ret);
167	}
168
169	return hw;
170}
171
172static bool clk_main_rc_osc_ready(struct regmap *regmap)
173{
174	unsigned int status;
175
176	regmap_read(regmap, AT91_PMC_SR, &status);
177
178	return !!(status & AT91_PMC_MOSCRCS);
179}
180
181static int clk_main_rc_osc_prepare(struct clk_hw *hw)
182{
183	struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
184	struct regmap *regmap = osc->regmap;
185	unsigned int mor;
186
187	regmap_read(regmap, AT91_CKGR_MOR, &mor);
188
189	if (!(mor & AT91_PMC_MOSCRCEN))
190		regmap_update_bits(regmap, AT91_CKGR_MOR,
191				   MOR_KEY_MASK | AT91_PMC_MOSCRCEN,
192				   AT91_PMC_MOSCRCEN | AT91_PMC_KEY);
193
194	while (!clk_main_rc_osc_ready(regmap))
195		cpu_relax();
196
197	return 0;
198}
199
200static void clk_main_rc_osc_unprepare(struct clk_hw *hw)
201{
202	struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
203	struct regmap *regmap = osc->regmap;
204	unsigned int mor;
205
206	regmap_read(regmap, AT91_CKGR_MOR, &mor);
207
208	if (!(mor & AT91_PMC_MOSCRCEN))
209		return;
210
211	regmap_update_bits(regmap, AT91_CKGR_MOR,
212			   MOR_KEY_MASK | AT91_PMC_MOSCRCEN, AT91_PMC_KEY);
213}
214
215static int clk_main_rc_osc_is_prepared(struct clk_hw *hw)
216{
217	struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
218	struct regmap *regmap = osc->regmap;
219	unsigned int mor, status;
220
221	regmap_read(regmap, AT91_CKGR_MOR, &mor);
222	regmap_read(regmap, AT91_PMC_SR, &status);
223
224	return (mor & AT91_PMC_MOSCRCEN) && (status & AT91_PMC_MOSCRCS);
225}
226
227static unsigned long clk_main_rc_osc_recalc_rate(struct clk_hw *hw,
228						 unsigned long parent_rate)
229{
230	struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
231
232	return osc->frequency;
233}
234
235static unsigned long clk_main_rc_osc_recalc_accuracy(struct clk_hw *hw,
236						     unsigned long parent_acc)
237{
238	struct clk_main_rc_osc *osc = to_clk_main_rc_osc(hw);
239
240	return osc->accuracy;
241}
242
243static const struct clk_ops main_rc_osc_ops = {
244	.prepare = clk_main_rc_osc_prepare,
245	.unprepare = clk_main_rc_osc_unprepare,
246	.is_prepared = clk_main_rc_osc_is_prepared,
247	.recalc_rate = clk_main_rc_osc_recalc_rate,
248	.recalc_accuracy = clk_main_rc_osc_recalc_accuracy,
249};
250
251struct clk_hw * __init
252at91_clk_register_main_rc_osc(struct regmap *regmap,
253			      const char *name,
254			      u32 frequency, u32 accuracy)
255{
256	struct clk_main_rc_osc *osc;
257	struct clk_init_data init;
258	struct clk_hw *hw;
259	int ret;
260
261	if (!name || !frequency)
262		return ERR_PTR(-EINVAL);
263
264	osc = kzalloc(sizeof(*osc), GFP_KERNEL);
265	if (!osc)
266		return ERR_PTR(-ENOMEM);
267
268	init.name = name;
269	init.ops = &main_rc_osc_ops;
270	init.parent_names = NULL;
271	init.num_parents = 0;
272	init.flags = CLK_IGNORE_UNUSED;
273
274	osc->hw.init = &init;
275	osc->regmap = regmap;
276	osc->frequency = frequency;
277	osc->accuracy = accuracy;
278
279	hw = &osc->hw;
280	ret = clk_hw_register(NULL, hw);
281	if (ret) {
282		kfree(osc);
283		hw = ERR_PTR(ret);
284	}
285
286	return hw;
287}
288
289static int clk_main_probe_frequency(struct regmap *regmap)
290{
291	unsigned long prep_time, timeout;
292	unsigned int mcfr;
293
294	timeout = jiffies + usecs_to_jiffies(MAINFRDY_TIMEOUT);
295	do {
296		prep_time = jiffies;
297		regmap_read(regmap, AT91_CKGR_MCFR, &mcfr);
298		if (mcfr & AT91_PMC_MAINRDY)
299			return 0;
300		if (system_state < SYSTEM_RUNNING)
301			udelay(MAINF_LOOP_MIN_WAIT);
302		else
303			usleep_range(MAINF_LOOP_MIN_WAIT, MAINF_LOOP_MAX_WAIT);
304	} while (time_before(prep_time, timeout));
305
306	return -ETIMEDOUT;
307}
308
309static unsigned long clk_main_recalc_rate(struct regmap *regmap,
310					  unsigned long parent_rate)
311{
312	unsigned int mcfr;
313
314	if (parent_rate)
315		return parent_rate;
316
317	pr_warn("Main crystal frequency not set, using approximate value\n");
318	regmap_read(regmap, AT91_CKGR_MCFR, &mcfr);
319	if (!(mcfr & AT91_PMC_MAINRDY))
320		return 0;
321
322	return ((mcfr & AT91_PMC_MAINF) * SLOW_CLOCK_FREQ) / MAINF_DIV;
323}
324
325static int clk_rm9200_main_prepare(struct clk_hw *hw)
326{
327	struct clk_rm9200_main *clkmain = to_clk_rm9200_main(hw);
328
329	return clk_main_probe_frequency(clkmain->regmap);
330}
331
332static int clk_rm9200_main_is_prepared(struct clk_hw *hw)
333{
334	struct clk_rm9200_main *clkmain = to_clk_rm9200_main(hw);
335	unsigned int status;
336
337	regmap_read(clkmain->regmap, AT91_CKGR_MCFR, &status);
338
339	return !!(status & AT91_PMC_MAINRDY);
340}
341
342static unsigned long clk_rm9200_main_recalc_rate(struct clk_hw *hw,
343						 unsigned long parent_rate)
344{
345	struct clk_rm9200_main *clkmain = to_clk_rm9200_main(hw);
346
347	return clk_main_recalc_rate(clkmain->regmap, parent_rate);
348}
349
350static const struct clk_ops rm9200_main_ops = {
351	.prepare = clk_rm9200_main_prepare,
352	.is_prepared = clk_rm9200_main_is_prepared,
353	.recalc_rate = clk_rm9200_main_recalc_rate,
354};
355
356struct clk_hw * __init
357at91_clk_register_rm9200_main(struct regmap *regmap,
358			      const char *name,
359			      const char *parent_name)
360{
361	struct clk_rm9200_main *clkmain;
362	struct clk_init_data init;
363	struct clk_hw *hw;
364	int ret;
365
366	if (!name)
367		return ERR_PTR(-EINVAL);
368
369	if (!parent_name)
370		return ERR_PTR(-EINVAL);
371
372	clkmain = kzalloc(sizeof(*clkmain), GFP_KERNEL);
373	if (!clkmain)
374		return ERR_PTR(-ENOMEM);
375
376	init.name = name;
377	init.ops = &rm9200_main_ops;
378	init.parent_names = &parent_name;
379	init.num_parents = 1;
380	init.flags = 0;
381
382	clkmain->hw.init = &init;
383	clkmain->regmap = regmap;
384
385	hw = &clkmain->hw;
386	ret = clk_hw_register(NULL, &clkmain->hw);
387	if (ret) {
388		kfree(clkmain);
389		hw = ERR_PTR(ret);
390	}
391
392	return hw;
393}
394
395static inline bool clk_sam9x5_main_ready(struct regmap *regmap)
396{
397	unsigned int status;
398
399	regmap_read(regmap, AT91_PMC_SR, &status);
400
401	return !!(status & AT91_PMC_MOSCSELS);
402}
403
404static int clk_sam9x5_main_prepare(struct clk_hw *hw)
405{
406	struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
407	struct regmap *regmap = clkmain->regmap;
408
409	while (!clk_sam9x5_main_ready(regmap))
410		cpu_relax();
411
412	return clk_main_probe_frequency(regmap);
413}
414
415static int clk_sam9x5_main_is_prepared(struct clk_hw *hw)
416{
417	struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
418
419	return clk_sam9x5_main_ready(clkmain->regmap);
420}
421
422static unsigned long clk_sam9x5_main_recalc_rate(struct clk_hw *hw,
423						 unsigned long parent_rate)
424{
425	struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
426
427	return clk_main_recalc_rate(clkmain->regmap, parent_rate);
428}
429
430static int clk_sam9x5_main_set_parent(struct clk_hw *hw, u8 index)
431{
432	struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
433	struct regmap *regmap = clkmain->regmap;
434	unsigned int tmp;
435
436	if (index > 1)
437		return -EINVAL;
438
439	regmap_read(regmap, AT91_CKGR_MOR, &tmp);
440
441	if (index && !(tmp & AT91_PMC_MOSCSEL))
442		tmp = AT91_PMC_MOSCSEL;
443	else if (!index && (tmp & AT91_PMC_MOSCSEL))
444		tmp = 0;
445	else
446		return 0;
447
448	regmap_update_bits(regmap, AT91_CKGR_MOR,
449			   AT91_PMC_MOSCSEL | MOR_KEY_MASK,
450			   tmp | AT91_PMC_KEY);
451
452	while (!clk_sam9x5_main_ready(regmap))
453		cpu_relax();
454
455	return 0;
456}
457
458static u8 clk_sam9x5_main_get_parent(struct clk_hw *hw)
459{
460	struct clk_sam9x5_main *clkmain = to_clk_sam9x5_main(hw);
461	unsigned int status;
462
463	regmap_read(clkmain->regmap, AT91_CKGR_MOR, &status);
464
465	return clk_main_parent_select(status);
466}
467
468static const struct clk_ops sam9x5_main_ops = {
469	.prepare = clk_sam9x5_main_prepare,
470	.is_prepared = clk_sam9x5_main_is_prepared,
471	.recalc_rate = clk_sam9x5_main_recalc_rate,
472	.set_parent = clk_sam9x5_main_set_parent,
473	.get_parent = clk_sam9x5_main_get_parent,
474};
475
476struct clk_hw * __init
477at91_clk_register_sam9x5_main(struct regmap *regmap,
478			      const char *name,
479			      const char **parent_names,
480			      int num_parents)
481{
482	struct clk_sam9x5_main *clkmain;
483	struct clk_init_data init;
484	unsigned int status;
485	struct clk_hw *hw;
486	int ret;
487
488	if (!name)
489		return ERR_PTR(-EINVAL);
490
491	if (!parent_names || !num_parents)
492		return ERR_PTR(-EINVAL);
493
494	clkmain = kzalloc(sizeof(*clkmain), GFP_KERNEL);
495	if (!clkmain)
496		return ERR_PTR(-ENOMEM);
497
498	init.name = name;
499	init.ops = &sam9x5_main_ops;
500	init.parent_names = parent_names;
501	init.num_parents = num_parents;
502	init.flags = CLK_SET_PARENT_GATE;
503
504	clkmain->hw.init = &init;
505	clkmain->regmap = regmap;
506	regmap_read(clkmain->regmap, AT91_CKGR_MOR, &status);
507	clkmain->parent = clk_main_parent_select(status);
508
509	hw = &clkmain->hw;
510	ret = clk_hw_register(NULL, &clkmain->hw);
511	if (ret) {
512		kfree(clkmain);
513		hw = ERR_PTR(ret);
514	}
515
516	return hw;
517}