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>
23 static struct clk
*cpuclk
;
25 static int at32_verify_speed(struct cpufreq_policy
*policy
)
30 cpufreq_verify_within_limits(policy
, policy
->cpuinfo
.min_freq
,
31 policy
->cpuinfo
.max_freq
);
35 static unsigned int at32_get_speed(unsigned int cpu
)
40 return (unsigned int)((clk_get_rate(cpuclk
) + 500) / 1000);
43 static unsigned int ref_freq
;
44 static unsigned long loops_per_jiffy_ref
;
46 static int at32_set_target(struct cpufreq_policy
*policy
,
47 unsigned int target_freq
,
48 unsigned int relation
)
50 struct cpufreq_freqs freqs
;
53 /* Convert target_freq from kHz to Hz */
54 freq
= clk_round_rate(cpuclk
, target_freq
* 1000);
56 /* Check if policy->min <= new_freq <= policy->max */
57 if(freq
< (policy
->min
* 1000) || freq
> (policy
->max
* 1000))
60 pr_debug("cpufreq: requested frequency %u Hz\n", target_freq
* 1000);
62 freqs
.old
= at32_get_speed(0);
63 freqs
.new = (freq
+ 500) / 1000;
68 loops_per_jiffy_ref
= boot_cpu_data
.loops_per_jiffy
;
71 cpufreq_notify_transition(policy
, &freqs
, CPUFREQ_PRECHANGE
);
72 if (freqs
.old
< freqs
.new)
73 boot_cpu_data
.loops_per_jiffy
= cpufreq_scale(
74 loops_per_jiffy_ref
, ref_freq
, freqs
.new);
75 clk_set_rate(cpuclk
, freq
);
76 if (freqs
.new < freqs
.old
)
77 boot_cpu_data
.loops_per_jiffy
= cpufreq_scale(
78 loops_per_jiffy_ref
, ref_freq
, freqs
.new);
79 cpufreq_notify_transition(policy
, &freqs
, CPUFREQ_POSTCHANGE
);
81 pr_debug("cpufreq: set frequency %lu Hz\n", freq
);
86 static int __init
at32_cpufreq_driver_init(struct cpufreq_policy
*policy
)
91 cpuclk
= clk_get(NULL
, "cpu");
93 pr_debug("cpufreq: could not get CPU clk\n");
94 return PTR_ERR(cpuclk
);
97 policy
->cpuinfo
.min_freq
= (clk_round_rate(cpuclk
, 1) + 500) / 1000;
98 policy
->cpuinfo
.max_freq
= (clk_round_rate(cpuclk
, ~0UL) + 500) / 1000;
99 policy
->cpuinfo
.transition_latency
= 0;
100 policy
->cur
= at32_get_speed(0);
101 policy
->min
= policy
->cpuinfo
.min_freq
;
102 policy
->max
= policy
->cpuinfo
.max_freq
;
104 printk("cpufreq: AT32AP CPU frequency driver\n");
109 static struct cpufreq_driver at32_driver
= {
111 .init
= at32_cpufreq_driver_init
,
112 .verify
= at32_verify_speed
,
113 .target
= at32_set_target
,
114 .get
= at32_get_speed
,
115 .flags
= CPUFREQ_STICKY
,
118 static int __init
at32_cpufreq_init(void)
120 return cpufreq_register_driver(&at32_driver
);
122 late_initcall(at32_cpufreq_init
);