Linux Audio

Check our new training course

Loading...
v3.1
  1/* linux/arch/arm/plat-s3c24xx/cpu-freq.c
  2 *
  3 * Copyright (c) 2006-2008 Simtec Electronics
  4 *	http://armlinux.simtec.co.uk/
  5 *	Ben Dooks <ben@simtec.co.uk>
  6 *
  7 * S3C24XX CPU Frequency scaling
  8 *
  9 * This program is free software; you can redistribute it and/or modify
 10 * it under the terms of the GNU General Public License version 2 as
 11 * published by the Free Software Foundation.
 12*/
 13
 14#include <linux/init.h>
 15#include <linux/module.h>
 16#include <linux/interrupt.h>
 17#include <linux/ioport.h>
 18#include <linux/cpufreq.h>
 19#include <linux/cpu.h>
 20#include <linux/clk.h>
 21#include <linux/err.h>
 22#include <linux/io.h>
 23#include <linux/sysdev.h>
 24#include <linux/sysfs.h>
 25#include <linux/slab.h>
 26
 27#include <asm/mach/arch.h>
 28#include <asm/mach/map.h>
 29
 30#include <plat/cpu.h>
 31#include <plat/clock.h>
 32#include <plat/cpu-freq-core.h>
 33
 34#include <mach/regs-clock.h>
 35
 36/* note, cpufreq support deals in kHz, no Hz */
 37
 38static struct cpufreq_driver s3c24xx_driver;
 39static struct s3c_cpufreq_config cpu_cur;
 40static struct s3c_iotimings s3c24xx_iotiming;
 41static struct cpufreq_frequency_table *pll_reg;
 42static unsigned int last_target = ~0;
 43static unsigned int ftab_size;
 44static struct cpufreq_frequency_table *ftab;
 45
 46static struct clk *_clk_mpll;
 47static struct clk *_clk_xtal;
 48static struct clk *clk_fclk;
 49static struct clk *clk_hclk;
 50static struct clk *clk_pclk;
 51static struct clk *clk_arm;
 52
 53#ifdef CONFIG_CPU_FREQ_S3C24XX_DEBUGFS
 54struct s3c_cpufreq_config *s3c_cpufreq_getconfig(void)
 55{
 56	return &cpu_cur;
 57}
 58
 59struct s3c_iotimings *s3c_cpufreq_getiotimings(void)
 60{
 61	return &s3c24xx_iotiming;
 62}
 63#endif /* CONFIG_CPU_FREQ_S3C24XX_DEBUGFS */
 64
 65static void s3c_cpufreq_getcur(struct s3c_cpufreq_config *cfg)
 66{
 67	unsigned long fclk, pclk, hclk, armclk;
 68
 69	cfg->freq.fclk = fclk = clk_get_rate(clk_fclk);
 70	cfg->freq.hclk = hclk = clk_get_rate(clk_hclk);
 71	cfg->freq.pclk = pclk = clk_get_rate(clk_pclk);
 72	cfg->freq.armclk = armclk = clk_get_rate(clk_arm);
 73
 74	cfg->pll.index = __raw_readl(S3C2410_MPLLCON);
 75	cfg->pll.frequency = fclk;
 76
 77	cfg->freq.hclk_tns = 1000000000 / (cfg->freq.hclk / 10);
 78
 79	cfg->divs.h_divisor = fclk / hclk;
 80	cfg->divs.p_divisor = fclk / pclk;
 81}
 82
 83static inline void s3c_cpufreq_calc(struct s3c_cpufreq_config *cfg)
 84{
 85	unsigned long pll = cfg->pll.frequency;
 86
 87	cfg->freq.fclk = pll;
 88	cfg->freq.hclk = pll / cfg->divs.h_divisor;
 89	cfg->freq.pclk = pll / cfg->divs.p_divisor;
 90
 91	/* convert hclk into 10ths of nanoseconds for io calcs */
 92	cfg->freq.hclk_tns = 1000000000 / (cfg->freq.hclk / 10);
 93}
 94
 95static inline int closer(unsigned int target, unsigned int n, unsigned int c)
 96{
 97	int diff_cur = abs(target - c);
 98	int diff_new = abs(target - n);
 99
100	return (diff_new < diff_cur);
101}
102
103static void s3c_cpufreq_show(const char *pfx,
104				 struct s3c_cpufreq_config *cfg)
105{
106	s3c_freq_dbg("%s: Fvco=%u, F=%lu, A=%lu, H=%lu (%u), P=%lu (%u)\n",
107		     pfx, cfg->pll.frequency, cfg->freq.fclk, cfg->freq.armclk,
108		     cfg->freq.hclk, cfg->divs.h_divisor,
109		     cfg->freq.pclk, cfg->divs.p_divisor);
110}
111
112/* functions to wrapper the driver info calls to do the cpu specific work */
113
114static void s3c_cpufreq_setio(struct s3c_cpufreq_config *cfg)
115{
116	if (cfg->info->set_iotiming)
117		(cfg->info->set_iotiming)(cfg, &s3c24xx_iotiming);
118}
119
120static int s3c_cpufreq_calcio(struct s3c_cpufreq_config *cfg)
121{
122	if (cfg->info->calc_iotiming)
123		return (cfg->info->calc_iotiming)(cfg, &s3c24xx_iotiming);
124
125	return 0;
126}
127
128static void s3c_cpufreq_setrefresh(struct s3c_cpufreq_config *cfg)
129{
130	(cfg->info->set_refresh)(cfg);
131}
132
133static void s3c_cpufreq_setdivs(struct s3c_cpufreq_config *cfg)
134{
135	(cfg->info->set_divs)(cfg);
136}
137
138static int s3c_cpufreq_calcdivs(struct s3c_cpufreq_config *cfg)
139{
140	return (cfg->info->calc_divs)(cfg);
141}
142
143static void s3c_cpufreq_setfvco(struct s3c_cpufreq_config *cfg)
144{
145	(cfg->info->set_fvco)(cfg);
146}
147
148static inline void s3c_cpufreq_resume_clocks(void)
149{
150	cpu_cur.info->resume_clocks();
151}
152
153static inline void s3c_cpufreq_updateclk(struct clk *clk,
154					 unsigned int freq)
155{
156	clk_set_rate(clk, freq);
157}
158
159static int s3c_cpufreq_settarget(struct cpufreq_policy *policy,
160				 unsigned int target_freq,
161				 struct cpufreq_frequency_table *pll)
162{
163	struct s3c_cpufreq_freqs freqs;
164	struct s3c_cpufreq_config cpu_new;
165	unsigned long flags;
166
167	cpu_new = cpu_cur;  /* copy new from current */
168
169	s3c_cpufreq_show("cur", &cpu_cur);
170
171	/* TODO - check for DMA currently outstanding */
172
173	cpu_new.pll = pll ? *pll : cpu_cur.pll;
174
175	if (pll)
176		freqs.pll_changing = 1;
177
178	/* update our frequencies */
179
180	cpu_new.freq.armclk = target_freq;
181	cpu_new.freq.fclk = cpu_new.pll.frequency;
182
183	if (s3c_cpufreq_calcdivs(&cpu_new) < 0) {
184		printk(KERN_ERR "no divisors for %d\n", target_freq);
185		goto err_notpossible;
186	}
187
188	s3c_freq_dbg("%s: got divs\n", __func__);
189
190	s3c_cpufreq_calc(&cpu_new);
191
192	s3c_freq_dbg("%s: calculated frequencies for new\n", __func__);
193
194	if (cpu_new.freq.hclk != cpu_cur.freq.hclk) {
195		if (s3c_cpufreq_calcio(&cpu_new) < 0) {
196			printk(KERN_ERR "%s: no IO timings\n", __func__);
197			goto err_notpossible;
198		}
199	}
200
201	s3c_cpufreq_show("new", &cpu_new);
202
203	/* setup our cpufreq parameters */
204
205	freqs.old = cpu_cur.freq;
206	freqs.new = cpu_new.freq;
207
208	freqs.freqs.cpu = 0;
209	freqs.freqs.old = cpu_cur.freq.armclk / 1000;
210	freqs.freqs.new = cpu_new.freq.armclk / 1000;
211
212	/* update f/h/p clock settings before we issue the change
213	 * notification, so that drivers do not need to do anything
214	 * special if they want to recalculate on CPUFREQ_PRECHANGE. */
215
216	s3c_cpufreq_updateclk(_clk_mpll, cpu_new.pll.frequency);
217	s3c_cpufreq_updateclk(clk_fclk, cpu_new.freq.fclk);
218	s3c_cpufreq_updateclk(clk_hclk, cpu_new.freq.hclk);
219	s3c_cpufreq_updateclk(clk_pclk, cpu_new.freq.pclk);
220
221	/* start the frequency change */
222
223	if (policy)
224		cpufreq_notify_transition(&freqs.freqs, CPUFREQ_PRECHANGE);
225
226	/* If hclk is staying the same, then we do not need to
227	 * re-write the IO or the refresh timings whilst we are changing
228	 * speed. */
229
230	local_irq_save(flags);
231
232	/* is our memory clock slowing down? */
233	if (cpu_new.freq.hclk < cpu_cur.freq.hclk) {
234		s3c_cpufreq_setrefresh(&cpu_new);
235		s3c_cpufreq_setio(&cpu_new);
236	}
237
238	if (cpu_new.freq.fclk == cpu_cur.freq.fclk) {
239		/* not changing PLL, just set the divisors */
240
241		s3c_cpufreq_setdivs(&cpu_new);
242	} else {
243		if (cpu_new.freq.fclk < cpu_cur.freq.fclk) {
244			/* slow the cpu down, then set divisors */
245
246			s3c_cpufreq_setfvco(&cpu_new);
247			s3c_cpufreq_setdivs(&cpu_new);
248		} else {
249			/* set the divisors, then speed up */
250
251			s3c_cpufreq_setdivs(&cpu_new);
252			s3c_cpufreq_setfvco(&cpu_new);
253		}
254	}
255
256	/* did our memory clock speed up */
257	if (cpu_new.freq.hclk > cpu_cur.freq.hclk) {
258		s3c_cpufreq_setrefresh(&cpu_new);
259		s3c_cpufreq_setio(&cpu_new);
260	}
261
262	/* update our current settings */
263	cpu_cur = cpu_new;
264
265	local_irq_restore(flags);
266
267	/* notify everyone we've done this */
268	if (policy)
269		cpufreq_notify_transition(&freqs.freqs, CPUFREQ_POSTCHANGE);
270
271	s3c_freq_dbg("%s: finished\n", __func__);
272	return 0;
273
274 err_notpossible:
275	printk(KERN_ERR "no compatible settings for %d\n", target_freq);
276	return -EINVAL;
277}
278
279/* s3c_cpufreq_target
280 *
281 * called by the cpufreq core to adjust the frequency that the CPU
282 * is currently running at.
283 */
284
285static int s3c_cpufreq_target(struct cpufreq_policy *policy,
286			      unsigned int target_freq,
287			      unsigned int relation)
288{
289	struct cpufreq_frequency_table *pll;
290	unsigned int index;
291
292	/* avoid repeated calls which cause a needless amout of duplicated
293	 * logging output (and CPU time as the calculation process is
294	 * done) */
295	if (target_freq == last_target)
296		return 0;
297
298	last_target = target_freq;
299
300	s3c_freq_dbg("%s: policy %p, target %u, relation %u\n",
301		     __func__, policy, target_freq, relation);
302
303	if (ftab) {
304		if (cpufreq_frequency_table_target(policy, ftab,
305						   target_freq, relation,
306						   &index)) {
307			s3c_freq_dbg("%s: table failed\n", __func__);
308			return -EINVAL;
309		}
310
311		s3c_freq_dbg("%s: adjust %d to entry %d (%u)\n", __func__,
312			     target_freq, index, ftab[index].frequency);
313		target_freq = ftab[index].frequency;
314	}
315
316	target_freq *= 1000;  /* convert target to Hz */
317
318	/* find the settings for our new frequency */
319
320	if (!pll_reg || cpu_cur.lock_pll) {
321		/* either we've not got any PLL values, or we've locked
322		 * to the current one. */
323		pll = NULL;
324	} else {
325		struct cpufreq_policy tmp_policy;
326		int ret;
327
328		/* we keep the cpu pll table in Hz, to ensure we get an
329		 * accurate value for the PLL output. */
330
331		tmp_policy.min = policy->min * 1000;
332		tmp_policy.max = policy->max * 1000;
333		tmp_policy.cpu = policy->cpu;
334
335		/* cpufreq_frequency_table_target uses a pointer to 'index'
336		 * which is the number of the table entry, not the value of
337		 * the table entry's index field. */
338
339		ret = cpufreq_frequency_table_target(&tmp_policy, pll_reg,
340						     target_freq, relation,
341						     &index);
342
343		if (ret < 0) {
344			printk(KERN_ERR "%s: no PLL available\n", __func__);
345			goto err_notpossible;
346		}
347
348		pll = pll_reg + index;
349
350		s3c_freq_dbg("%s: target %u => %u\n",
351			     __func__, target_freq, pll->frequency);
352
353		target_freq = pll->frequency;
354	}
355
356	return s3c_cpufreq_settarget(policy, target_freq, pll);
357
358 err_notpossible:
359	printk(KERN_ERR "no compatible settings for %d\n", target_freq);
360	return -EINVAL;
361}
362
363static unsigned int s3c_cpufreq_get(unsigned int cpu)
364{
365	return clk_get_rate(clk_arm) / 1000;
366}
367
368struct clk *s3c_cpufreq_clk_get(struct device *dev, const char *name)
369{
370	struct clk *clk;
371
372	clk = clk_get(dev, name);
373	if (IS_ERR(clk))
374		printk(KERN_ERR "cpufreq: failed to get clock '%s'\n", name);
375
376	return clk;
377}
378
379static int s3c_cpufreq_init(struct cpufreq_policy *policy)
380{
381	printk(KERN_INFO "%s: initialising policy %p\n", __func__, policy);
382
383	if (policy->cpu != 0)
384		return -EINVAL;
385
386	policy->cur = s3c_cpufreq_get(0);
387	policy->min = policy->cpuinfo.min_freq = 0;
388	policy->max = policy->cpuinfo.max_freq = cpu_cur.info->max.fclk / 1000;
389	policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
390
391	/* feed the latency information from the cpu driver */
392	policy->cpuinfo.transition_latency = cpu_cur.info->latency;
393
394	if (ftab)
395		cpufreq_frequency_table_cpuinfo(policy, ftab);
396
397	return 0;
398}
399
400static __init int s3c_cpufreq_initclks(void)
401{
402	_clk_mpll = s3c_cpufreq_clk_get(NULL, "mpll");
403	_clk_xtal = s3c_cpufreq_clk_get(NULL, "xtal");
404	clk_fclk = s3c_cpufreq_clk_get(NULL, "fclk");
405	clk_hclk = s3c_cpufreq_clk_get(NULL, "hclk");
406	clk_pclk = s3c_cpufreq_clk_get(NULL, "pclk");
407	clk_arm = s3c_cpufreq_clk_get(NULL, "armclk");
408
409	if (IS_ERR(clk_fclk) || IS_ERR(clk_hclk) || IS_ERR(clk_pclk) ||
410	    IS_ERR(_clk_mpll) || IS_ERR(clk_arm) || IS_ERR(_clk_xtal)) {
411		printk(KERN_ERR "%s: could not get clock(s)\n", __func__);
412		return -ENOENT;
413	}
414
415	printk(KERN_INFO "%s: clocks f=%lu,h=%lu,p=%lu,a=%lu\n", __func__,
416	       clk_get_rate(clk_fclk) / 1000,
417	       clk_get_rate(clk_hclk) / 1000,
418	       clk_get_rate(clk_pclk) / 1000,
419	       clk_get_rate(clk_arm) / 1000);
420
421	return 0;
422}
423
424static int s3c_cpufreq_verify(struct cpufreq_policy *policy)
425{
426	if (policy->cpu != 0)
427		return -EINVAL;
428
429	return 0;
430}
431
432#ifdef CONFIG_PM
433static struct cpufreq_frequency_table suspend_pll;
434static unsigned int suspend_freq;
435
436static int s3c_cpufreq_suspend(struct cpufreq_policy *policy)
437{
438	suspend_pll.frequency = clk_get_rate(_clk_mpll);
439	suspend_pll.index = __raw_readl(S3C2410_MPLLCON);
440	suspend_freq = s3c_cpufreq_get(0) * 1000;
441
442	return 0;
443}
444
445static int s3c_cpufreq_resume(struct cpufreq_policy *policy)
446{
447	int ret;
448
449	s3c_freq_dbg("%s: resuming with policy %p\n", __func__, policy);
450
451	last_target = ~0;	/* invalidate last_target setting */
452
453	/* first, find out what speed we resumed at. */
454	s3c_cpufreq_resume_clocks();
455
456	/* whilst we will be called later on, we try and re-set the
457	 * cpu frequencies as soon as possible so that we do not end
458	 * up resuming devices and then immediately having to re-set
459	 * a number of settings once these devices have restarted.
460	 *
461	 * as a note, it is expected devices are not used until they
462	 * have been un-suspended and at that time they should have
463	 * used the updated clock settings.
464	 */
465
466	ret = s3c_cpufreq_settarget(NULL, suspend_freq, &suspend_pll);
467	if (ret) {
468		printk(KERN_ERR "%s: failed to reset pll/freq\n", __func__);
469		return ret;
470	}
471
472	return 0;
473}
474#else
475#define s3c_cpufreq_resume NULL
476#define s3c_cpufreq_suspend NULL
477#endif
478
479static struct cpufreq_driver s3c24xx_driver = {
480	.flags		= CPUFREQ_STICKY,
481	.verify		= s3c_cpufreq_verify,
482	.target		= s3c_cpufreq_target,
483	.get		= s3c_cpufreq_get,
484	.init		= s3c_cpufreq_init,
485	.suspend	= s3c_cpufreq_suspend,
486	.resume		= s3c_cpufreq_resume,
487	.name		= "s3c24xx",
488};
489
490
491int __init s3c_cpufreq_register(struct s3c_cpufreq_info *info)
492{
493	if (!info || !info->name) {
494		printk(KERN_ERR "%s: failed to pass valid information\n",
495		       __func__);
496		return -EINVAL;
497	}
498
499	printk(KERN_INFO "S3C24XX CPU Frequency driver, %s cpu support\n",
500	       info->name);
501
502	/* check our driver info has valid data */
503
504	BUG_ON(info->set_refresh == NULL);
505	BUG_ON(info->set_divs == NULL);
506	BUG_ON(info->calc_divs == NULL);
507
508	/* info->set_fvco is optional, depending on whether there
509	 * is a need to set the clock code. */
510
511	cpu_cur.info = info;
512
513	/* Note, driver registering should probably update locktime */
514
515	return 0;
516}
517
518int __init s3c_cpufreq_setboard(struct s3c_cpufreq_board *board)
519{
520	struct s3c_cpufreq_board *ours;
521
522	if (!board) {
523		printk(KERN_INFO "%s: no board data\n", __func__);
524		return -EINVAL;
525	}
526
527	/* Copy the board information so that each board can make this
528	 * initdata. */
529
530	ours = kzalloc(sizeof(struct s3c_cpufreq_board), GFP_KERNEL);
531	if (ours == NULL) {
532		printk(KERN_ERR "%s: no memory\n", __func__);
533		return -ENOMEM;
534	}
535
536	*ours = *board;
537	cpu_cur.board = ours;
538
539	return 0;
540}
541
542int __init s3c_cpufreq_auto_io(void)
543{
544	int ret;
545
546	if (!cpu_cur.info->get_iotiming) {
547		printk(KERN_ERR "%s: get_iotiming undefined\n", __func__);
548		return -ENOENT;
549	}
550
551	printk(KERN_INFO "%s: working out IO settings\n", __func__);
552
553	ret = (cpu_cur.info->get_iotiming)(&cpu_cur, &s3c24xx_iotiming);
554	if (ret)
555		printk(KERN_ERR "%s: failed to get timings\n", __func__);
556
557	return ret;
558}
559
560/* if one or is zero, then return the other, otherwise return the min */
561#define do_min(_a, _b) ((_a) == 0 ? (_b) : (_b) == 0 ? (_a) : min(_a, _b))
562
563/**
564 * s3c_cpufreq_freq_min - find the minimum settings for the given freq.
565 * @dst: The destination structure
566 * @a: One argument.
567 * @b: The other argument.
568 *
569 * Create a minimum of each frequency entry in the 'struct s3c_freq',
570 * unless the entry is zero when it is ignored and the non-zero argument
571 * used.
572 */
573static void s3c_cpufreq_freq_min(struct s3c_freq *dst,
574				 struct s3c_freq *a, struct s3c_freq *b)
575{
576	dst->fclk = do_min(a->fclk, b->fclk);
577	dst->hclk = do_min(a->hclk, b->hclk);
578	dst->pclk = do_min(a->pclk, b->pclk);
579	dst->armclk = do_min(a->armclk, b->armclk);
580}
581
582static inline u32 calc_locktime(u32 freq, u32 time_us)
583{
584	u32 result;
585
586	result = freq * time_us;
587	result = DIV_ROUND_UP(result, 1000 * 1000);
588
589	return result;
590}
591
592static void s3c_cpufreq_update_loctkime(void)
593{
594	unsigned int bits = cpu_cur.info->locktime_bits;
595	u32 rate = (u32)clk_get_rate(_clk_xtal);
596	u32 val;
597
598	if (bits == 0) {
599		WARN_ON(1);
600		return;
601	}
602
603	val = calc_locktime(rate, cpu_cur.info->locktime_u) << bits;
604	val |= calc_locktime(rate, cpu_cur.info->locktime_m);
605
606	printk(KERN_INFO "%s: new locktime is 0x%08x\n", __func__, val);
607	__raw_writel(val, S3C2410_LOCKTIME);
608}
609
610static int s3c_cpufreq_build_freq(void)
611{
612	int size, ret;
613
614	if (!cpu_cur.info->calc_freqtable)
615		return -EINVAL;
616
617	kfree(ftab);
618	ftab = NULL;
619
620	size = cpu_cur.info->calc_freqtable(&cpu_cur, NULL, 0);
621	size++;
622
623	ftab = kmalloc(sizeof(struct cpufreq_frequency_table) * size, GFP_KERNEL);
624	if (!ftab) {
625		printk(KERN_ERR "%s: no memory for tables\n", __func__);
626		return -ENOMEM;
627	}
628
629	ftab_size = size;
630
631	ret = cpu_cur.info->calc_freqtable(&cpu_cur, ftab, size);
632	s3c_cpufreq_addfreq(ftab, ret, size, CPUFREQ_TABLE_END);
633
634	return 0;
635}
636
637static int __init s3c_cpufreq_initcall(void)
638{
639	int ret = 0;
640
641	if (cpu_cur.info && cpu_cur.board) {
642		ret = s3c_cpufreq_initclks();
643		if (ret)
644			goto out;
645
646		/* get current settings */
647		s3c_cpufreq_getcur(&cpu_cur);
648		s3c_cpufreq_show("cur", &cpu_cur);
649
650		if (cpu_cur.board->auto_io) {
651			ret = s3c_cpufreq_auto_io();
652			if (ret) {
653				printk(KERN_ERR "%s: failed to get io timing\n",
654				       __func__);
655				goto out;
656			}
657		}
658
659		if (cpu_cur.board->need_io && !cpu_cur.info->set_iotiming) {
660			printk(KERN_ERR "%s: no IO support registered\n",
661			       __func__);
662			ret = -EINVAL;
663			goto out;
664		}
665
666		if (!cpu_cur.info->need_pll)
667			cpu_cur.lock_pll = 1;
668
669		s3c_cpufreq_update_loctkime();
670
671		s3c_cpufreq_freq_min(&cpu_cur.max, &cpu_cur.board->max,
672				     &cpu_cur.info->max);
673
674		if (cpu_cur.info->calc_freqtable)
675			s3c_cpufreq_build_freq();
676
677		ret = cpufreq_register_driver(&s3c24xx_driver);
678	}
679
680 out:
681	return ret;
682}
683
684late_initcall(s3c_cpufreq_initcall);
685
686/**
687 * s3c_plltab_register - register CPU PLL table.
688 * @plls: The list of PLL entries.
689 * @plls_no: The size of the PLL entries @plls.
690 *
691 * Register the given set of PLLs with the system.
692 */
693int __init s3c_plltab_register(struct cpufreq_frequency_table *plls,
694			       unsigned int plls_no)
695{
696	struct cpufreq_frequency_table *vals;
697	unsigned int size;
698
699	size = sizeof(struct cpufreq_frequency_table) * (plls_no + 1);
700
701	vals = kmalloc(size, GFP_KERNEL);
702	if (vals) {
703		memcpy(vals, plls, size);
704		pll_reg = vals;
705
706		/* write a terminating entry, we don't store it in the
707		 * table that is stored in the kernel */
708		vals += plls_no;
709		vals->frequency = CPUFREQ_TABLE_END;
710
711		printk(KERN_INFO "cpufreq: %d PLL entries\n", plls_no);
712	} else
713		printk(KERN_ERR "cpufreq: no memory for PLL tables\n");
714
715	return vals ? 0 : -ENOMEM;
716}
v3.5.6
  1/* linux/arch/arm/plat-s3c24xx/cpu-freq.c
  2 *
  3 * Copyright (c) 2006-2008 Simtec Electronics
  4 *	http://armlinux.simtec.co.uk/
  5 *	Ben Dooks <ben@simtec.co.uk>
  6 *
  7 * S3C24XX CPU Frequency scaling
  8 *
  9 * This program is free software; you can redistribute it and/or modify
 10 * it under the terms of the GNU General Public License version 2 as
 11 * published by the Free Software Foundation.
 12*/
 13
 14#include <linux/init.h>
 15#include <linux/module.h>
 16#include <linux/interrupt.h>
 17#include <linux/ioport.h>
 18#include <linux/cpufreq.h>
 19#include <linux/cpu.h>
 20#include <linux/clk.h>
 21#include <linux/err.h>
 22#include <linux/io.h>
 23#include <linux/device.h>
 24#include <linux/sysfs.h>
 25#include <linux/slab.h>
 26
 27#include <asm/mach/arch.h>
 28#include <asm/mach/map.h>
 29
 30#include <plat/cpu.h>
 31#include <plat/clock.h>
 32#include <plat/cpu-freq-core.h>
 33
 34#include <mach/regs-clock.h>
 35
 36/* note, cpufreq support deals in kHz, no Hz */
 37
 38static struct cpufreq_driver s3c24xx_driver;
 39static struct s3c_cpufreq_config cpu_cur;
 40static struct s3c_iotimings s3c24xx_iotiming;
 41static struct cpufreq_frequency_table *pll_reg;
 42static unsigned int last_target = ~0;
 43static unsigned int ftab_size;
 44static struct cpufreq_frequency_table *ftab;
 45
 46static struct clk *_clk_mpll;
 47static struct clk *_clk_xtal;
 48static struct clk *clk_fclk;
 49static struct clk *clk_hclk;
 50static struct clk *clk_pclk;
 51static struct clk *clk_arm;
 52
 53#ifdef CONFIG_CPU_FREQ_S3C24XX_DEBUGFS
 54struct s3c_cpufreq_config *s3c_cpufreq_getconfig(void)
 55{
 56	return &cpu_cur;
 57}
 58
 59struct s3c_iotimings *s3c_cpufreq_getiotimings(void)
 60{
 61	return &s3c24xx_iotiming;
 62}
 63#endif /* CONFIG_CPU_FREQ_S3C24XX_DEBUGFS */
 64
 65static void s3c_cpufreq_getcur(struct s3c_cpufreq_config *cfg)
 66{
 67	unsigned long fclk, pclk, hclk, armclk;
 68
 69	cfg->freq.fclk = fclk = clk_get_rate(clk_fclk);
 70	cfg->freq.hclk = hclk = clk_get_rate(clk_hclk);
 71	cfg->freq.pclk = pclk = clk_get_rate(clk_pclk);
 72	cfg->freq.armclk = armclk = clk_get_rate(clk_arm);
 73
 74	cfg->pll.index = __raw_readl(S3C2410_MPLLCON);
 75	cfg->pll.frequency = fclk;
 76
 77	cfg->freq.hclk_tns = 1000000000 / (cfg->freq.hclk / 10);
 78
 79	cfg->divs.h_divisor = fclk / hclk;
 80	cfg->divs.p_divisor = fclk / pclk;
 81}
 82
 83static inline void s3c_cpufreq_calc(struct s3c_cpufreq_config *cfg)
 84{
 85	unsigned long pll = cfg->pll.frequency;
 86
 87	cfg->freq.fclk = pll;
 88	cfg->freq.hclk = pll / cfg->divs.h_divisor;
 89	cfg->freq.pclk = pll / cfg->divs.p_divisor;
 90
 91	/* convert hclk into 10ths of nanoseconds for io calcs */
 92	cfg->freq.hclk_tns = 1000000000 / (cfg->freq.hclk / 10);
 93}
 94
 95static inline int closer(unsigned int target, unsigned int n, unsigned int c)
 96{
 97	int diff_cur = abs(target - c);
 98	int diff_new = abs(target - n);
 99
100	return (diff_new < diff_cur);
101}
102
103static void s3c_cpufreq_show(const char *pfx,
104				 struct s3c_cpufreq_config *cfg)
105{
106	s3c_freq_dbg("%s: Fvco=%u, F=%lu, A=%lu, H=%lu (%u), P=%lu (%u)\n",
107		     pfx, cfg->pll.frequency, cfg->freq.fclk, cfg->freq.armclk,
108		     cfg->freq.hclk, cfg->divs.h_divisor,
109		     cfg->freq.pclk, cfg->divs.p_divisor);
110}
111
112/* functions to wrapper the driver info calls to do the cpu specific work */
113
114static void s3c_cpufreq_setio(struct s3c_cpufreq_config *cfg)
115{
116	if (cfg->info->set_iotiming)
117		(cfg->info->set_iotiming)(cfg, &s3c24xx_iotiming);
118}
119
120static int s3c_cpufreq_calcio(struct s3c_cpufreq_config *cfg)
121{
122	if (cfg->info->calc_iotiming)
123		return (cfg->info->calc_iotiming)(cfg, &s3c24xx_iotiming);
124
125	return 0;
126}
127
128static void s3c_cpufreq_setrefresh(struct s3c_cpufreq_config *cfg)
129{
130	(cfg->info->set_refresh)(cfg);
131}
132
133static void s3c_cpufreq_setdivs(struct s3c_cpufreq_config *cfg)
134{
135	(cfg->info->set_divs)(cfg);
136}
137
138static int s3c_cpufreq_calcdivs(struct s3c_cpufreq_config *cfg)
139{
140	return (cfg->info->calc_divs)(cfg);
141}
142
143static void s3c_cpufreq_setfvco(struct s3c_cpufreq_config *cfg)
144{
145	(cfg->info->set_fvco)(cfg);
146}
147
148static inline void s3c_cpufreq_resume_clocks(void)
149{
150	cpu_cur.info->resume_clocks();
151}
152
153static inline void s3c_cpufreq_updateclk(struct clk *clk,
154					 unsigned int freq)
155{
156	clk_set_rate(clk, freq);
157}
158
159static int s3c_cpufreq_settarget(struct cpufreq_policy *policy,
160				 unsigned int target_freq,
161				 struct cpufreq_frequency_table *pll)
162{
163	struct s3c_cpufreq_freqs freqs;
164	struct s3c_cpufreq_config cpu_new;
165	unsigned long flags;
166
167	cpu_new = cpu_cur;  /* copy new from current */
168
169	s3c_cpufreq_show("cur", &cpu_cur);
170
171	/* TODO - check for DMA currently outstanding */
172
173	cpu_new.pll = pll ? *pll : cpu_cur.pll;
174
175	if (pll)
176		freqs.pll_changing = 1;
177
178	/* update our frequencies */
179
180	cpu_new.freq.armclk = target_freq;
181	cpu_new.freq.fclk = cpu_new.pll.frequency;
182
183	if (s3c_cpufreq_calcdivs(&cpu_new) < 0) {
184		printk(KERN_ERR "no divisors for %d\n", target_freq);
185		goto err_notpossible;
186	}
187
188	s3c_freq_dbg("%s: got divs\n", __func__);
189
190	s3c_cpufreq_calc(&cpu_new);
191
192	s3c_freq_dbg("%s: calculated frequencies for new\n", __func__);
193
194	if (cpu_new.freq.hclk != cpu_cur.freq.hclk) {
195		if (s3c_cpufreq_calcio(&cpu_new) < 0) {
196			printk(KERN_ERR "%s: no IO timings\n", __func__);
197			goto err_notpossible;
198		}
199	}
200
201	s3c_cpufreq_show("new", &cpu_new);
202
203	/* setup our cpufreq parameters */
204
205	freqs.old = cpu_cur.freq;
206	freqs.new = cpu_new.freq;
207
208	freqs.freqs.cpu = 0;
209	freqs.freqs.old = cpu_cur.freq.armclk / 1000;
210	freqs.freqs.new = cpu_new.freq.armclk / 1000;
211
212	/* update f/h/p clock settings before we issue the change
213	 * notification, so that drivers do not need to do anything
214	 * special if they want to recalculate on CPUFREQ_PRECHANGE. */
215
216	s3c_cpufreq_updateclk(_clk_mpll, cpu_new.pll.frequency);
217	s3c_cpufreq_updateclk(clk_fclk, cpu_new.freq.fclk);
218	s3c_cpufreq_updateclk(clk_hclk, cpu_new.freq.hclk);
219	s3c_cpufreq_updateclk(clk_pclk, cpu_new.freq.pclk);
220
221	/* start the frequency change */
222
223	if (policy)
224		cpufreq_notify_transition(&freqs.freqs, CPUFREQ_PRECHANGE);
225
226	/* If hclk is staying the same, then we do not need to
227	 * re-write the IO or the refresh timings whilst we are changing
228	 * speed. */
229
230	local_irq_save(flags);
231
232	/* is our memory clock slowing down? */
233	if (cpu_new.freq.hclk < cpu_cur.freq.hclk) {
234		s3c_cpufreq_setrefresh(&cpu_new);
235		s3c_cpufreq_setio(&cpu_new);
236	}
237
238	if (cpu_new.freq.fclk == cpu_cur.freq.fclk) {
239		/* not changing PLL, just set the divisors */
240
241		s3c_cpufreq_setdivs(&cpu_new);
242	} else {
243		if (cpu_new.freq.fclk < cpu_cur.freq.fclk) {
244			/* slow the cpu down, then set divisors */
245
246			s3c_cpufreq_setfvco(&cpu_new);
247			s3c_cpufreq_setdivs(&cpu_new);
248		} else {
249			/* set the divisors, then speed up */
250
251			s3c_cpufreq_setdivs(&cpu_new);
252			s3c_cpufreq_setfvco(&cpu_new);
253		}
254	}
255
256	/* did our memory clock speed up */
257	if (cpu_new.freq.hclk > cpu_cur.freq.hclk) {
258		s3c_cpufreq_setrefresh(&cpu_new);
259		s3c_cpufreq_setio(&cpu_new);
260	}
261
262	/* update our current settings */
263	cpu_cur = cpu_new;
264
265	local_irq_restore(flags);
266
267	/* notify everyone we've done this */
268	if (policy)
269		cpufreq_notify_transition(&freqs.freqs, CPUFREQ_POSTCHANGE);
270
271	s3c_freq_dbg("%s: finished\n", __func__);
272	return 0;
273
274 err_notpossible:
275	printk(KERN_ERR "no compatible settings for %d\n", target_freq);
276	return -EINVAL;
277}
278
279/* s3c_cpufreq_target
280 *
281 * called by the cpufreq core to adjust the frequency that the CPU
282 * is currently running at.
283 */
284
285static int s3c_cpufreq_target(struct cpufreq_policy *policy,
286			      unsigned int target_freq,
287			      unsigned int relation)
288{
289	struct cpufreq_frequency_table *pll;
290	unsigned int index;
291
292	/* avoid repeated calls which cause a needless amout of duplicated
293	 * logging output (and CPU time as the calculation process is
294	 * done) */
295	if (target_freq == last_target)
296		return 0;
297
298	last_target = target_freq;
299
300	s3c_freq_dbg("%s: policy %p, target %u, relation %u\n",
301		     __func__, policy, target_freq, relation);
302
303	if (ftab) {
304		if (cpufreq_frequency_table_target(policy, ftab,
305						   target_freq, relation,
306						   &index)) {
307			s3c_freq_dbg("%s: table failed\n", __func__);
308			return -EINVAL;
309		}
310
311		s3c_freq_dbg("%s: adjust %d to entry %d (%u)\n", __func__,
312			     target_freq, index, ftab[index].frequency);
313		target_freq = ftab[index].frequency;
314	}
315
316	target_freq *= 1000;  /* convert target to Hz */
317
318	/* find the settings for our new frequency */
319
320	if (!pll_reg || cpu_cur.lock_pll) {
321		/* either we've not got any PLL values, or we've locked
322		 * to the current one. */
323		pll = NULL;
324	} else {
325		struct cpufreq_policy tmp_policy;
326		int ret;
327
328		/* we keep the cpu pll table in Hz, to ensure we get an
329		 * accurate value for the PLL output. */
330
331		tmp_policy.min = policy->min * 1000;
332		tmp_policy.max = policy->max * 1000;
333		tmp_policy.cpu = policy->cpu;
334
335		/* cpufreq_frequency_table_target uses a pointer to 'index'
336		 * which is the number of the table entry, not the value of
337		 * the table entry's index field. */
338
339		ret = cpufreq_frequency_table_target(&tmp_policy, pll_reg,
340						     target_freq, relation,
341						     &index);
342
343		if (ret < 0) {
344			printk(KERN_ERR "%s: no PLL available\n", __func__);
345			goto err_notpossible;
346		}
347
348		pll = pll_reg + index;
349
350		s3c_freq_dbg("%s: target %u => %u\n",
351			     __func__, target_freq, pll->frequency);
352
353		target_freq = pll->frequency;
354	}
355
356	return s3c_cpufreq_settarget(policy, target_freq, pll);
357
358 err_notpossible:
359	printk(KERN_ERR "no compatible settings for %d\n", target_freq);
360	return -EINVAL;
361}
362
363static unsigned int s3c_cpufreq_get(unsigned int cpu)
364{
365	return clk_get_rate(clk_arm) / 1000;
366}
367
368struct clk *s3c_cpufreq_clk_get(struct device *dev, const char *name)
369{
370	struct clk *clk;
371
372	clk = clk_get(dev, name);
373	if (IS_ERR(clk))
374		printk(KERN_ERR "cpufreq: failed to get clock '%s'\n", name);
375
376	return clk;
377}
378
379static int s3c_cpufreq_init(struct cpufreq_policy *policy)
380{
381	printk(KERN_INFO "%s: initialising policy %p\n", __func__, policy);
382
383	if (policy->cpu != 0)
384		return -EINVAL;
385
386	policy->cur = s3c_cpufreq_get(0);
387	policy->min = policy->cpuinfo.min_freq = 0;
388	policy->max = policy->cpuinfo.max_freq = cpu_cur.info->max.fclk / 1000;
389	policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
390
391	/* feed the latency information from the cpu driver */
392	policy->cpuinfo.transition_latency = cpu_cur.info->latency;
393
394	if (ftab)
395		cpufreq_frequency_table_cpuinfo(policy, ftab);
396
397	return 0;
398}
399
400static __init int s3c_cpufreq_initclks(void)
401{
402	_clk_mpll = s3c_cpufreq_clk_get(NULL, "mpll");
403	_clk_xtal = s3c_cpufreq_clk_get(NULL, "xtal");
404	clk_fclk = s3c_cpufreq_clk_get(NULL, "fclk");
405	clk_hclk = s3c_cpufreq_clk_get(NULL, "hclk");
406	clk_pclk = s3c_cpufreq_clk_get(NULL, "pclk");
407	clk_arm = s3c_cpufreq_clk_get(NULL, "armclk");
408
409	if (IS_ERR(clk_fclk) || IS_ERR(clk_hclk) || IS_ERR(clk_pclk) ||
410	    IS_ERR(_clk_mpll) || IS_ERR(clk_arm) || IS_ERR(_clk_xtal)) {
411		printk(KERN_ERR "%s: could not get clock(s)\n", __func__);
412		return -ENOENT;
413	}
414
415	printk(KERN_INFO "%s: clocks f=%lu,h=%lu,p=%lu,a=%lu\n", __func__,
416	       clk_get_rate(clk_fclk) / 1000,
417	       clk_get_rate(clk_hclk) / 1000,
418	       clk_get_rate(clk_pclk) / 1000,
419	       clk_get_rate(clk_arm) / 1000);
420
421	return 0;
422}
423
424static int s3c_cpufreq_verify(struct cpufreq_policy *policy)
425{
426	if (policy->cpu != 0)
427		return -EINVAL;
428
429	return 0;
430}
431
432#ifdef CONFIG_PM
433static struct cpufreq_frequency_table suspend_pll;
434static unsigned int suspend_freq;
435
436static int s3c_cpufreq_suspend(struct cpufreq_policy *policy)
437{
438	suspend_pll.frequency = clk_get_rate(_clk_mpll);
439	suspend_pll.index = __raw_readl(S3C2410_MPLLCON);
440	suspend_freq = s3c_cpufreq_get(0) * 1000;
441
442	return 0;
443}
444
445static int s3c_cpufreq_resume(struct cpufreq_policy *policy)
446{
447	int ret;
448
449	s3c_freq_dbg("%s: resuming with policy %p\n", __func__, policy);
450
451	last_target = ~0;	/* invalidate last_target setting */
452
453	/* first, find out what speed we resumed at. */
454	s3c_cpufreq_resume_clocks();
455
456	/* whilst we will be called later on, we try and re-set the
457	 * cpu frequencies as soon as possible so that we do not end
458	 * up resuming devices and then immediately having to re-set
459	 * a number of settings once these devices have restarted.
460	 *
461	 * as a note, it is expected devices are not used until they
462	 * have been un-suspended and at that time they should have
463	 * used the updated clock settings.
464	 */
465
466	ret = s3c_cpufreq_settarget(NULL, suspend_freq, &suspend_pll);
467	if (ret) {
468		printk(KERN_ERR "%s: failed to reset pll/freq\n", __func__);
469		return ret;
470	}
471
472	return 0;
473}
474#else
475#define s3c_cpufreq_resume NULL
476#define s3c_cpufreq_suspend NULL
477#endif
478
479static struct cpufreq_driver s3c24xx_driver = {
480	.flags		= CPUFREQ_STICKY,
481	.verify		= s3c_cpufreq_verify,
482	.target		= s3c_cpufreq_target,
483	.get		= s3c_cpufreq_get,
484	.init		= s3c_cpufreq_init,
485	.suspend	= s3c_cpufreq_suspend,
486	.resume		= s3c_cpufreq_resume,
487	.name		= "s3c24xx",
488};
489
490
491int __init s3c_cpufreq_register(struct s3c_cpufreq_info *info)
492{
493	if (!info || !info->name) {
494		printk(KERN_ERR "%s: failed to pass valid information\n",
495		       __func__);
496		return -EINVAL;
497	}
498
499	printk(KERN_INFO "S3C24XX CPU Frequency driver, %s cpu support\n",
500	       info->name);
501
502	/* check our driver info has valid data */
503
504	BUG_ON(info->set_refresh == NULL);
505	BUG_ON(info->set_divs == NULL);
506	BUG_ON(info->calc_divs == NULL);
507
508	/* info->set_fvco is optional, depending on whether there
509	 * is a need to set the clock code. */
510
511	cpu_cur.info = info;
512
513	/* Note, driver registering should probably update locktime */
514
515	return 0;
516}
517
518int __init s3c_cpufreq_setboard(struct s3c_cpufreq_board *board)
519{
520	struct s3c_cpufreq_board *ours;
521
522	if (!board) {
523		printk(KERN_INFO "%s: no board data\n", __func__);
524		return -EINVAL;
525	}
526
527	/* Copy the board information so that each board can make this
528	 * initdata. */
529
530	ours = kzalloc(sizeof(struct s3c_cpufreq_board), GFP_KERNEL);
531	if (ours == NULL) {
532		printk(KERN_ERR "%s: no memory\n", __func__);
533		return -ENOMEM;
534	}
535
536	*ours = *board;
537	cpu_cur.board = ours;
538
539	return 0;
540}
541
542int __init s3c_cpufreq_auto_io(void)
543{
544	int ret;
545
546	if (!cpu_cur.info->get_iotiming) {
547		printk(KERN_ERR "%s: get_iotiming undefined\n", __func__);
548		return -ENOENT;
549	}
550
551	printk(KERN_INFO "%s: working out IO settings\n", __func__);
552
553	ret = (cpu_cur.info->get_iotiming)(&cpu_cur, &s3c24xx_iotiming);
554	if (ret)
555		printk(KERN_ERR "%s: failed to get timings\n", __func__);
556
557	return ret;
558}
559
560/* if one or is zero, then return the other, otherwise return the min */
561#define do_min(_a, _b) ((_a) == 0 ? (_b) : (_b) == 0 ? (_a) : min(_a, _b))
562
563/**
564 * s3c_cpufreq_freq_min - find the minimum settings for the given freq.
565 * @dst: The destination structure
566 * @a: One argument.
567 * @b: The other argument.
568 *
569 * Create a minimum of each frequency entry in the 'struct s3c_freq',
570 * unless the entry is zero when it is ignored and the non-zero argument
571 * used.
572 */
573static void s3c_cpufreq_freq_min(struct s3c_freq *dst,
574				 struct s3c_freq *a, struct s3c_freq *b)
575{
576	dst->fclk = do_min(a->fclk, b->fclk);
577	dst->hclk = do_min(a->hclk, b->hclk);
578	dst->pclk = do_min(a->pclk, b->pclk);
579	dst->armclk = do_min(a->armclk, b->armclk);
580}
581
582static inline u32 calc_locktime(u32 freq, u32 time_us)
583{
584	u32 result;
585
586	result = freq * time_us;
587	result = DIV_ROUND_UP(result, 1000 * 1000);
588
589	return result;
590}
591
592static void s3c_cpufreq_update_loctkime(void)
593{
594	unsigned int bits = cpu_cur.info->locktime_bits;
595	u32 rate = (u32)clk_get_rate(_clk_xtal);
596	u32 val;
597
598	if (bits == 0) {
599		WARN_ON(1);
600		return;
601	}
602
603	val = calc_locktime(rate, cpu_cur.info->locktime_u) << bits;
604	val |= calc_locktime(rate, cpu_cur.info->locktime_m);
605
606	printk(KERN_INFO "%s: new locktime is 0x%08x\n", __func__, val);
607	__raw_writel(val, S3C2410_LOCKTIME);
608}
609
610static int s3c_cpufreq_build_freq(void)
611{
612	int size, ret;
613
614	if (!cpu_cur.info->calc_freqtable)
615		return -EINVAL;
616
617	kfree(ftab);
618	ftab = NULL;
619
620	size = cpu_cur.info->calc_freqtable(&cpu_cur, NULL, 0);
621	size++;
622
623	ftab = kmalloc(sizeof(struct cpufreq_frequency_table) * size, GFP_KERNEL);
624	if (!ftab) {
625		printk(KERN_ERR "%s: no memory for tables\n", __func__);
626		return -ENOMEM;
627	}
628
629	ftab_size = size;
630
631	ret = cpu_cur.info->calc_freqtable(&cpu_cur, ftab, size);
632	s3c_cpufreq_addfreq(ftab, ret, size, CPUFREQ_TABLE_END);
633
634	return 0;
635}
636
637static int __init s3c_cpufreq_initcall(void)
638{
639	int ret = 0;
640
641	if (cpu_cur.info && cpu_cur.board) {
642		ret = s3c_cpufreq_initclks();
643		if (ret)
644			goto out;
645
646		/* get current settings */
647		s3c_cpufreq_getcur(&cpu_cur);
648		s3c_cpufreq_show("cur", &cpu_cur);
649
650		if (cpu_cur.board->auto_io) {
651			ret = s3c_cpufreq_auto_io();
652			if (ret) {
653				printk(KERN_ERR "%s: failed to get io timing\n",
654				       __func__);
655				goto out;
656			}
657		}
658
659		if (cpu_cur.board->need_io && !cpu_cur.info->set_iotiming) {
660			printk(KERN_ERR "%s: no IO support registered\n",
661			       __func__);
662			ret = -EINVAL;
663			goto out;
664		}
665
666		if (!cpu_cur.info->need_pll)
667			cpu_cur.lock_pll = 1;
668
669		s3c_cpufreq_update_loctkime();
670
671		s3c_cpufreq_freq_min(&cpu_cur.max, &cpu_cur.board->max,
672				     &cpu_cur.info->max);
673
674		if (cpu_cur.info->calc_freqtable)
675			s3c_cpufreq_build_freq();
676
677		ret = cpufreq_register_driver(&s3c24xx_driver);
678	}
679
680 out:
681	return ret;
682}
683
684late_initcall(s3c_cpufreq_initcall);
685
686/**
687 * s3c_plltab_register - register CPU PLL table.
688 * @plls: The list of PLL entries.
689 * @plls_no: The size of the PLL entries @plls.
690 *
691 * Register the given set of PLLs with the system.
692 */
693int __init s3c_plltab_register(struct cpufreq_frequency_table *plls,
694			       unsigned int plls_no)
695{
696	struct cpufreq_frequency_table *vals;
697	unsigned int size;
698
699	size = sizeof(struct cpufreq_frequency_table) * (plls_no + 1);
700
701	vals = kmalloc(size, GFP_KERNEL);
702	if (vals) {
703		memcpy(vals, plls, size);
704		pll_reg = vals;
705
706		/* write a terminating entry, we don't store it in the
707		 * table that is stored in the kernel */
708		vals += plls_no;
709		vals->frequency = CPUFREQ_TABLE_END;
710
711		printk(KERN_INFO "cpufreq: %d PLL entries\n", plls_no);
712	} else
713		printk(KERN_ERR "cpufreq: no memory for PLL tables\n");
714
715	return vals ? 0 : -ENOMEM;
716}