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/dbx500-prcmu.h>
18 static struct cpufreq_frequency_table freq_table
[] = {
32 /* Used for MAX_OPP, if available */
34 .frequency
= CPUFREQ_TABLE_END
,
38 .frequency
= CPUFREQ_TABLE_END
,
42 static enum arm_opp idx2opp
[] = {
49 static struct freq_attr
*db8500_cpufreq_attr
[] = {
50 &cpufreq_freq_attr_scaling_available_freqs
,
54 static int db8500_cpufreq_verify_speed(struct cpufreq_policy
*policy
)
56 return cpufreq_frequency_table_verify(policy
, freq_table
);
59 static int db8500_cpufreq_target(struct cpufreq_policy
*policy
,
60 unsigned int target_freq
,
61 unsigned int relation
)
63 struct cpufreq_freqs freqs
;
66 /* scale the target frequency to one of the extremes supported */
67 if (target_freq
< policy
->cpuinfo
.min_freq
)
68 target_freq
= policy
->cpuinfo
.min_freq
;
69 if (target_freq
> policy
->cpuinfo
.max_freq
)
70 target_freq
= policy
->cpuinfo
.max_freq
;
72 /* Lookup the next frequency */
73 if (cpufreq_frequency_table_target
74 (policy
, freq_table
, target_freq
, relation
, &idx
)) {
78 freqs
.old
= policy
->cur
;
79 freqs
.new = freq_table
[idx
].frequency
;
81 if (freqs
.old
== freqs
.new)
84 /* pre-change notification */
85 for_each_cpu(freqs
.cpu
, policy
->cpus
)
86 cpufreq_notify_transition(&freqs
, CPUFREQ_PRECHANGE
);
88 /* request the PRCM unit for opp change */
89 if (prcmu_set_arm_opp(idx2opp
[idx
])) {
90 pr_err("db8500-cpufreq: Failed to set OPP level\n");
94 /* post change notification */
95 for_each_cpu(freqs
.cpu
, policy
->cpus
)
96 cpufreq_notify_transition(&freqs
, CPUFREQ_POSTCHANGE
);
101 static unsigned int db8500_cpufreq_getspeed(unsigned int cpu
)
104 /* request the prcm to get the current ARM opp */
105 for (i
= 0; prcmu_get_arm_opp() != idx2opp
[i
]; i
++)
107 return freq_table
[i
].frequency
;
110 static int __cpuinit
db8500_cpufreq_init(struct cpufreq_policy
*policy
)
114 BUILD_BUG_ON(ARRAY_SIZE(idx2opp
) + 1 != ARRAY_SIZE(freq_table
));
116 if (prcmu_has_arm_maxopp())
117 freq_table
[3].frequency
= 1000000;
119 pr_info("db8500-cpufreq : Available frequencies:\n");
120 for (i
= 0; freq_table
[i
].frequency
!= CPUFREQ_TABLE_END
; i
++)
121 pr_info(" %d Mhz\n", freq_table
[i
].frequency
/1000);
123 /* get policy fields based on the table */
124 res
= cpufreq_frequency_table_cpuinfo(policy
, freq_table
);
126 cpufreq_frequency_table_get_attr(freq_table
, policy
->cpu
);
128 pr_err("db8500-cpufreq : Failed to read policy table\n");
132 policy
->min
= policy
->cpuinfo
.min_freq
;
133 policy
->max
= policy
->cpuinfo
.max_freq
;
134 policy
->cur
= db8500_cpufreq_getspeed(policy
->cpu
);
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_mask
);
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
);