2 * Copyright (C) 2004-2007 Atmel Corporation
4 * Based on MIPS implementation arch/mips/kernel/time.c
5 * Copyright 2001 MontaVista Software Inc.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
14 #include <linux/kernel.h>
15 #include <linux/types.h>
16 #include <linux/init.h>
17 #include <linux/cpufreq.h>
19 #include <linux/clk.h>
20 #include <linux/err.h>
21 #include <linux/export.h>
22 #include <linux/slab.h>
24 static struct cpufreq_frequency_table
*freq_table
;
26 static unsigned int ref_freq
;
27 static unsigned long loops_per_jiffy_ref
;
29 static int at32_set_target(struct cpufreq_policy
*policy
, unsigned int index
)
31 unsigned int old_freq
, new_freq
;
33 old_freq
= policy
->cur
;
34 new_freq
= freq_table
[index
].frequency
;
38 loops_per_jiffy_ref
= boot_cpu_data
.loops_per_jiffy
;
41 if (old_freq
< new_freq
)
42 boot_cpu_data
.loops_per_jiffy
= cpufreq_scale(
43 loops_per_jiffy_ref
, ref_freq
, new_freq
);
44 clk_set_rate(policy
->clk
, new_freq
* 1000);
45 if (new_freq
< old_freq
)
46 boot_cpu_data
.loops_per_jiffy
= cpufreq_scale(
47 loops_per_jiffy_ref
, ref_freq
, new_freq
);
52 static int at32_cpufreq_driver_init(struct cpufreq_policy
*policy
)
54 unsigned int frequency
, rate
, min_freq
;
55 static struct clk
*cpuclk
;
61 cpuclk
= clk_get(NULL
, "cpu");
63 pr_debug("cpufreq: could not get CPU clk\n");
64 retval
= PTR_ERR(cpuclk
);
68 min_freq
= (clk_round_rate(cpuclk
, 1) + 500) / 1000;
69 frequency
= (clk_round_rate(cpuclk
, ~0UL) + 500) / 1000;
70 policy
->cpuinfo
.transition_latency
= 0;
73 * AVR32 CPU frequency rate scales in power of two between maximum and
74 * minimum, also add space for the table end marker.
76 * Further validate that the frequency is usable, and append it to the
79 steps
= fls(frequency
/ min_freq
) + 1;
80 freq_table
= kzalloc(steps
* sizeof(struct cpufreq_frequency_table
),
87 for (i
= 0; i
< (steps
- 1); i
++) {
88 rate
= clk_round_rate(cpuclk
, frequency
* 1000) / 1000;
90 if (rate
!= frequency
)
91 freq_table
[i
].frequency
= CPUFREQ_ENTRY_INVALID
;
93 freq_table
[i
].frequency
= frequency
;
99 freq_table
[steps
- 1].frequency
= CPUFREQ_TABLE_END
;
101 retval
= cpufreq_table_validate_and_show(policy
, freq_table
);
103 printk("cpufreq: AT32AP CPU frequency driver\n");
114 static struct cpufreq_driver at32_driver
= {
116 .init
= at32_cpufreq_driver_init
,
117 .verify
= cpufreq_generic_frequency_table_verify
,
118 .target_index
= at32_set_target
,
119 .get
= cpufreq_generic_get
,
120 .flags
= CPUFREQ_STICKY
,
123 static int __init
at32_cpufreq_init(void)
125 return cpufreq_register_driver(&at32_driver
);
127 late_initcall(at32_cpufreq_init
);