aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/cpufreq/kirkwood-cpufreq.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/cpufreq/kirkwood-cpufreq.c')
-rw-r--r--drivers/cpufreq/kirkwood-cpufreq.c107
1 files changed, 26 insertions, 81 deletions
diff --git a/drivers/cpufreq/kirkwood-cpufreq.c b/drivers/cpufreq/kirkwood-cpufreq.c
index ba10658a9394..0767a4e29dfe 100644
--- a/drivers/cpufreq/kirkwood-cpufreq.c
+++ b/drivers/cpufreq/kirkwood-cpufreq.c
@@ -55,69 +55,37 @@ static unsigned int kirkwood_cpufreq_get_cpu_frequency(unsigned int cpu)
55 return kirkwood_freq_table[0].frequency; 55 return kirkwood_freq_table[0].frequency;
56} 56}
57 57
58static void kirkwood_cpufreq_set_cpu_state(struct cpufreq_policy *policy, 58static int kirkwood_cpufreq_target(struct cpufreq_policy *policy,
59 unsigned int index) 59 unsigned int index)
60{ 60{
61 struct cpufreq_freqs freqs;
62 unsigned int state = kirkwood_freq_table[index].driver_data; 61 unsigned int state = kirkwood_freq_table[index].driver_data;
63 unsigned long reg; 62 unsigned long reg;
64 63
65 freqs.old = kirkwood_cpufreq_get_cpu_frequency(0); 64 local_irq_disable();
66 freqs.new = kirkwood_freq_table[index].frequency;
67
68 cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
69
70 dev_dbg(priv.dev, "Attempting to set frequency to %i KHz\n",
71 kirkwood_freq_table[index].frequency);
72 dev_dbg(priv.dev, "old frequency was %i KHz\n",
73 kirkwood_cpufreq_get_cpu_frequency(0));
74
75 if (freqs.old != freqs.new) {
76 local_irq_disable();
77
78 /* Disable interrupts to the CPU */
79 reg = readl_relaxed(priv.base);
80 reg |= CPU_SW_INT_BLK;
81 writel_relaxed(reg, priv.base);
82
83 switch (state) {
84 case STATE_CPU_FREQ:
85 clk_disable(priv.powersave_clk);
86 break;
87 case STATE_DDR_FREQ:
88 clk_enable(priv.powersave_clk);
89 break;
90 }
91 65
92 /* Wait-for-Interrupt, while the hardware changes frequency */ 66 /* Disable interrupts to the CPU */
93 cpu_do_idle(); 67 reg = readl_relaxed(priv.base);
68 reg |= CPU_SW_INT_BLK;
69 writel_relaxed(reg, priv.base);
94 70
95 /* Enable interrupts to the CPU */ 71 switch (state) {
96 reg = readl_relaxed(priv.base); 72 case STATE_CPU_FREQ:
97 reg &= ~CPU_SW_INT_BLK; 73 clk_disable(priv.powersave_clk);
98 writel_relaxed(reg, priv.base); 74 break;
99 75 case STATE_DDR_FREQ:
100 local_irq_enable(); 76 clk_enable(priv.powersave_clk);
77 break;
101 } 78 }
102 cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
103};
104
105static int kirkwood_cpufreq_verify(struct cpufreq_policy *policy)
106{
107 return cpufreq_frequency_table_verify(policy, kirkwood_freq_table);
108}
109 79
110static int kirkwood_cpufreq_target(struct cpufreq_policy *policy, 80 /* Wait-for-Interrupt, while the hardware changes frequency */
111 unsigned int target_freq, 81 cpu_do_idle();
112 unsigned int relation)
113{
114 unsigned int index = 0;
115 82
116 if (cpufreq_frequency_table_target(policy, kirkwood_freq_table, 83 /* Enable interrupts to the CPU */
117 target_freq, relation, &index)) 84 reg = readl_relaxed(priv.base);
118 return -EINVAL; 85 reg &= ~CPU_SW_INT_BLK;
86 writel_relaxed(reg, priv.base);
119 87
120 kirkwood_cpufreq_set_cpu_state(policy, index); 88 local_irq_enable();
121 89
122 return 0; 90 return 0;
123} 91}
@@ -125,40 +93,17 @@ static int kirkwood_cpufreq_target(struct cpufreq_policy *policy,
125/* Module init and exit code */ 93/* Module init and exit code */
126static int kirkwood_cpufreq_cpu_init(struct cpufreq_policy *policy) 94static int kirkwood_cpufreq_cpu_init(struct cpufreq_policy *policy)
127{ 95{
128 int result; 96 return cpufreq_generic_init(policy, kirkwood_freq_table, 5000);
129
130 /* cpuinfo and default policy values */
131 policy->cpuinfo.transition_latency = 5000; /* 5uS */
132 policy->cur = kirkwood_cpufreq_get_cpu_frequency(0);
133
134 result = cpufreq_frequency_table_cpuinfo(policy, kirkwood_freq_table);
135 if (result)
136 return result;
137
138 cpufreq_frequency_table_get_attr(kirkwood_freq_table, policy->cpu);
139
140 return 0;
141}
142
143static int kirkwood_cpufreq_cpu_exit(struct cpufreq_policy *policy)
144{
145 cpufreq_frequency_table_put_attr(policy->cpu);
146 return 0;
147} 97}
148 98
149static struct freq_attr *kirkwood_cpufreq_attr[] = {
150 &cpufreq_freq_attr_scaling_available_freqs,
151 NULL,
152};
153
154static struct cpufreq_driver kirkwood_cpufreq_driver = { 99static struct cpufreq_driver kirkwood_cpufreq_driver = {
155 .get = kirkwood_cpufreq_get_cpu_frequency, 100 .get = kirkwood_cpufreq_get_cpu_frequency,
156 .verify = kirkwood_cpufreq_verify, 101 .verify = cpufreq_generic_frequency_table_verify,
157 .target = kirkwood_cpufreq_target, 102 .target_index = kirkwood_cpufreq_target,
158 .init = kirkwood_cpufreq_cpu_init, 103 .init = kirkwood_cpufreq_cpu_init,
159 .exit = kirkwood_cpufreq_cpu_exit, 104 .exit = cpufreq_generic_exit,
160 .name = "kirkwood-cpufreq", 105 .name = "kirkwood-cpufreq",
161 .attr = kirkwood_cpufreq_attr, 106 .attr = cpufreq_generic_attr,
162}; 107};
163 108
164static int kirkwood_cpufreq_probe(struct platform_device *pdev) 109static int kirkwood_cpufreq_probe(struct platform_device *pdev)