2 * Copyright (C) STMicroelectronics 2009
3 * Copyright (C) ST-Ericsson SA 2010-2012
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>
19 static struct cpufreq_frequency_table
*freq_table
;
20 static struct clk
*armss_clk
;
22 static struct freq_attr
*dbx500_cpufreq_attr
[] = {
23 &cpufreq_freq_attr_scaling_available_freqs
,
27 static int dbx500_cpufreq_verify_speed(struct cpufreq_policy
*policy
)
29 return cpufreq_frequency_table_verify(policy
, freq_table
);
32 static int dbx500_cpufreq_target(struct cpufreq_policy
*policy
,
33 unsigned int target_freq
,
34 unsigned int relation
)
36 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(policy
, freq_table
, target_freq
,
51 freqs
.old
= policy
->cur
;
52 freqs
.new = freq_table
[idx
].frequency
;
54 if (freqs
.old
== freqs
.new)
57 /* pre-change notification */
58 for_each_cpu(freqs
.cpu
, policy
->cpus
)
59 cpufreq_notify_transition(&freqs
, CPUFREQ_PRECHANGE
);
61 /* update armss clk frequency */
62 ret
= clk_set_rate(armss_clk
, freqs
.new * 1000);
65 pr_err("dbx500-cpufreq: Failed to set armss_clk to %d Hz: error %d\n",
66 freqs
.new * 1000, ret
);
70 /* post change notification */
71 for_each_cpu(freqs
.cpu
, policy
->cpus
)
72 cpufreq_notify_transition(&freqs
, CPUFREQ_POSTCHANGE
);
77 static unsigned int dbx500_cpufreq_getspeed(unsigned int cpu
)
80 unsigned long freq
= clk_get_rate(armss_clk
) / 1000;
82 while (freq_table
[i
].frequency
!= CPUFREQ_TABLE_END
) {
83 if (freq
<= freq_table
[i
].frequency
)
84 return freq_table
[i
].frequency
;
88 /* We could not find a corresponding frequency. */
89 pr_err("dbx500-cpufreq: Failed to find cpufreq speed\n");
93 static int __cpuinit
dbx500_cpufreq_init(struct cpufreq_policy
*policy
)
97 /* get policy fields based on the table */
98 res
= cpufreq_frequency_table_cpuinfo(policy
, freq_table
);
100 cpufreq_frequency_table_get_attr(freq_table
, policy
->cpu
);
102 pr_err("dbx500-cpufreq: Failed to read policy table\n");
106 policy
->min
= policy
->cpuinfo
.min_freq
;
107 policy
->max
= policy
->cpuinfo
.max_freq
;
108 policy
->cur
= dbx500_cpufreq_getspeed(policy
->cpu
);
109 policy
->governor
= CPUFREQ_DEFAULT_GOVERNOR
;
112 * FIXME : Need to take time measurement across the target()
113 * function with no/some/all drivers in the notification
116 policy
->cpuinfo
.transition_latency
= 20 * 1000; /* in ns */
118 /* policy sharing between dual CPUs */
119 cpumask_setall(policy
->cpus
);
124 static struct cpufreq_driver dbx500_cpufreq_driver
= {
125 .flags
= CPUFREQ_STICKY
| CPUFREQ_CONST_LOOPS
,
126 .verify
= dbx500_cpufreq_verify_speed
,
127 .target
= dbx500_cpufreq_target
,
128 .get
= dbx500_cpufreq_getspeed
,
129 .init
= dbx500_cpufreq_init
,
131 .attr
= dbx500_cpufreq_attr
,
134 static int dbx500_cpufreq_probe(struct platform_device
*pdev
)
138 freq_table
= dev_get_platdata(&pdev
->dev
);
140 pr_err("dbx500-cpufreq: Failed to fetch cpufreq table\n");
144 armss_clk
= clk_get(&pdev
->dev
, "armss");
145 if (IS_ERR(armss_clk
)) {
146 pr_err("dbx500-cpufreq: Failed to get armss clk\n");
147 return PTR_ERR(armss_clk
);
150 pr_info("dbx500-cpufreq: Available frequencies:\n");
151 while (freq_table
[i
].frequency
!= CPUFREQ_TABLE_END
) {
152 pr_info(" %d Mhz\n", freq_table
[i
].frequency
/1000);
156 return cpufreq_register_driver(&dbx500_cpufreq_driver
);
159 static struct platform_driver dbx500_cpufreq_plat_driver
= {
161 .name
= "cpufreq-ux500",
162 .owner
= THIS_MODULE
,
164 .probe
= dbx500_cpufreq_probe
,
167 static int __init
dbx500_cpufreq_register(void)
169 return platform_driver_register(&dbx500_cpufreq_plat_driver
);
171 device_initcall(dbx500_cpufreq_register
);
173 MODULE_LICENSE("GPL v2");
174 MODULE_DESCRIPTION("cpufreq driver for DBX500");