2 * Copyright (C) STMicroelectronics 2009
3 * Copyright (C) ST-Ericsson SA 2010
5 * License Terms: GNU General Public License v2
6 * Author: Sundar Iyer <sundar.iyer@stericsson.com>
7 * Author: Martin Persson <martin.persson@stericsson.com>
8 * Author: Jonas Aaberg <jonas.aberg@stericsson.com>
11 #include <linux/module.h>
12 #include <linux/kernel.h>
13 #include <linux/cpufreq.h>
14 #include <linux/delay.h>
15 #include <linux/slab.h>
16 #include <linux/platform_device.h>
17 #include <linux/clk.h>
20 static struct cpufreq_frequency_table
*freq_table
;
21 static struct clk
*armss_clk
;
23 static struct freq_attr
*db8500_cpufreq_attr
[] = {
24 &cpufreq_freq_attr_scaling_available_freqs
,
28 static int db8500_cpufreq_verify_speed(struct cpufreq_policy
*policy
)
30 return cpufreq_frequency_table_verify(policy
, freq_table
);
33 static int db8500_cpufreq_target(struct cpufreq_policy
*policy
,
34 unsigned int target_freq
,
35 unsigned int relation
)
37 struct cpufreq_freqs freqs
;
40 /* scale the target frequency to one of the extremes supported */
41 if (target_freq
< policy
->cpuinfo
.min_freq
)
42 target_freq
= policy
->cpuinfo
.min_freq
;
43 if (target_freq
> policy
->cpuinfo
.max_freq
)
44 target_freq
= policy
->cpuinfo
.max_freq
;
46 /* Lookup the next frequency */
47 if (cpufreq_frequency_table_target
48 (policy
, freq_table
, target_freq
, relation
, &idx
)) {
52 freqs
.old
= policy
->cur
;
53 freqs
.new = freq_table
[idx
].frequency
;
55 if (freqs
.old
== freqs
.new)
58 /* pre-change notification */
59 for_each_cpu(freqs
.cpu
, policy
->cpus
)
60 cpufreq_notify_transition(&freqs
, CPUFREQ_PRECHANGE
);
62 /* update armss clk frequency */
63 if (clk_set_rate(armss_clk
, freq_table
[idx
].frequency
* 1000)) {
64 pr_err("db8500-cpufreq: Failed to update armss clk\n");
68 /* post change notification */
69 for_each_cpu(freqs
.cpu
, policy
->cpus
)
70 cpufreq_notify_transition(&freqs
, CPUFREQ_POSTCHANGE
);
75 static unsigned int db8500_cpufreq_getspeed(unsigned int cpu
)
78 unsigned long freq
= clk_get_rate(armss_clk
) / 1000;
80 while (freq_table
[i
].frequency
!= CPUFREQ_TABLE_END
) {
81 if (freq
<= freq_table
[i
].frequency
)
82 return freq_table
[i
].frequency
;
86 /* We could not find a corresponding frequency. */
87 pr_err("db8500-cpufreq: Failed to find cpufreq speed\n");
91 static int __cpuinit
db8500_cpufreq_init(struct cpufreq_policy
*policy
)
96 armss_clk
= clk_get(NULL
, "armss");
97 if (IS_ERR(armss_clk
)) {
98 pr_err("db8500-cpufreq : Failed to get armss clk\n");
99 return PTR_ERR(armss_clk
);
102 pr_info("db8500-cpufreq : Available frequencies:\n");
103 while (freq_table
[i
].frequency
!= CPUFREQ_TABLE_END
) {
104 pr_info(" %d Mhz\n", freq_table
[i
].frequency
/1000);
108 /* get policy fields based on the table */
109 res
= cpufreq_frequency_table_cpuinfo(policy
, freq_table
);
111 cpufreq_frequency_table_get_attr(freq_table
, policy
->cpu
);
113 pr_err("db8500-cpufreq : Failed to read policy table\n");
118 policy
->min
= policy
->cpuinfo
.min_freq
;
119 policy
->max
= policy
->cpuinfo
.max_freq
;
120 policy
->cur
= db8500_cpufreq_getspeed(policy
->cpu
);
121 policy
->governor
= CPUFREQ_DEFAULT_GOVERNOR
;
124 * FIXME : Need to take time measurement across the target()
125 * function with no/some/all drivers in the notification
128 policy
->cpuinfo
.transition_latency
= 20 * 1000; /* in ns */
130 /* policy sharing between dual CPUs */
131 cpumask_copy(policy
->cpus
, cpu_present_mask
);
133 policy
->shared_type
= CPUFREQ_SHARED_TYPE_ALL
;
138 static struct cpufreq_driver db8500_cpufreq_driver
= {
139 .flags
= CPUFREQ_STICKY
,
140 .verify
= db8500_cpufreq_verify_speed
,
141 .target
= db8500_cpufreq_target
,
142 .get
= db8500_cpufreq_getspeed
,
143 .init
= db8500_cpufreq_init
,
145 .attr
= db8500_cpufreq_attr
,
148 static int db8500_cpufreq_probe(struct platform_device
*pdev
)
150 freq_table
= dev_get_platdata(&pdev
->dev
);
153 pr_err("db8500-cpufreq: Failed to fetch cpufreq table\n");
157 return cpufreq_register_driver(&db8500_cpufreq_driver
);
160 static struct platform_driver db8500_cpufreq_plat_driver
= {
162 .name
= "cpufreq-u8500",
163 .owner
= THIS_MODULE
,
165 .probe
= db8500_cpufreq_probe
,
168 static int __init
db8500_cpufreq_register(void)
170 if (!cpu_is_u8500_family())
173 pr_info("cpufreq for DB8500 started\n");
174 return platform_driver_register(&db8500_cpufreq_plat_driver
);
176 device_initcall(db8500_cpufreq_register
);
178 MODULE_LICENSE("GPL v2");
179 MODULE_DESCRIPTION("cpufreq driver for DB8500");