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/kernel.h>
12 #include <linux/cpufreq.h>
13 #include <linux/delay.h>
14 #include <linux/slab.h>
15 #include <linux/mfd/db8500-prcmu.h>
18 static struct cpufreq_frequency_table freq_table
[] = {
28 /* Used for MAX_OPP, if available */
30 .frequency
= CPUFREQ_TABLE_END
,
34 .frequency
= CPUFREQ_TABLE_END
,
38 static enum arm_opp idx2opp
[] = {
44 static struct freq_attr
*db8500_cpufreq_attr
[] = {
45 &cpufreq_freq_attr_scaling_available_freqs
,
49 static int db8500_cpufreq_verify_speed(struct cpufreq_policy
*policy
)
51 return cpufreq_frequency_table_verify(policy
, freq_table
);
54 static int db8500_cpufreq_target(struct cpufreq_policy
*policy
,
55 unsigned int target_freq
,
56 unsigned int relation
)
58 struct cpufreq_freqs freqs
;
61 /* scale the target frequency to one of the extremes supported */
62 if (target_freq
< policy
->cpuinfo
.min_freq
)
63 target_freq
= policy
->cpuinfo
.min_freq
;
64 if (target_freq
> policy
->cpuinfo
.max_freq
)
65 target_freq
= policy
->cpuinfo
.max_freq
;
67 /* Lookup the next frequency */
68 if (cpufreq_frequency_table_target
69 (policy
, freq_table
, target_freq
, relation
, &idx
)) {
73 freqs
.old
= policy
->cur
;
74 freqs
.new = freq_table
[idx
].frequency
;
76 if (freqs
.old
== freqs
.new)
79 /* pre-change notification */
80 for_each_cpu(freqs
.cpu
, policy
->cpus
)
81 cpufreq_notify_transition(&freqs
, CPUFREQ_PRECHANGE
);
83 /* request the PRCM unit for opp change */
84 if (prcmu_set_arm_opp(idx2opp
[idx
])) {
85 pr_err("db8500-cpufreq: Failed to set OPP level\n");
89 /* post change notification */
90 for_each_cpu(freqs
.cpu
, policy
->cpus
)
91 cpufreq_notify_transition(&freqs
, CPUFREQ_POSTCHANGE
);
96 static unsigned int db8500_cpufreq_getspeed(unsigned int cpu
)
99 /* request the prcm to get the current ARM opp */
100 for (i
= 0; prcmu_get_arm_opp() != idx2opp
[i
]; i
++)
102 return freq_table
[i
].frequency
;
105 static int __cpuinit
db8500_cpufreq_init(struct cpufreq_policy
*policy
)
110 BUILD_BUG_ON(ARRAY_SIZE(idx2opp
) + 1 != ARRAY_SIZE(freq_table
));
112 if (cpu_is_u8500v2() && !prcmu_is_u8400()) {
113 freq_table
[0].frequency
= 400000;
114 freq_table
[1].frequency
= 800000;
115 if (prcmu_has_arm_maxopp())
116 freq_table
[2].frequency
= 1000000;
119 /* get policy fields based on the table */
120 res
= cpufreq_frequency_table_cpuinfo(policy
, freq_table
);
122 cpufreq_frequency_table_get_attr(freq_table
, policy
->cpu
);
124 pr_err("db8500-cpufreq : Failed to read policy table\n");
128 policy
->min
= policy
->cpuinfo
.min_freq
;
129 policy
->max
= policy
->cpuinfo
.max_freq
;
130 policy
->cur
= db8500_cpufreq_getspeed(policy
->cpu
);
132 for (i
= 0; freq_table
[i
].frequency
!= policy
->cur
; i
++)
135 policy
->governor
= CPUFREQ_DEFAULT_GOVERNOR
;
138 * FIXME : Need to take time measurement across the target()
139 * function with no/some/all drivers in the notification
142 policy
->cpuinfo
.transition_latency
= 20 * 1000; /* in ns */
144 /* policy sharing between dual CPUs */
145 cpumask_copy(policy
->cpus
, &cpu_present_map
);
147 policy
->shared_type
= CPUFREQ_SHARED_TYPE_ALL
;
152 static struct cpufreq_driver db8500_cpufreq_driver
= {
153 .flags
= CPUFREQ_STICKY
,
154 .verify
= db8500_cpufreq_verify_speed
,
155 .target
= db8500_cpufreq_target
,
156 .get
= db8500_cpufreq_getspeed
,
157 .init
= db8500_cpufreq_init
,
159 .attr
= db8500_cpufreq_attr
,
162 static int __init
db8500_cpufreq_register(void)
164 if (!cpu_is_u8500v20_or_later())
167 pr_info("cpufreq for DB8500 started\n");
168 return cpufreq_register_driver(&db8500_cpufreq_driver
);
170 device_initcall(db8500_cpufreq_register
);