diff options
Diffstat (limited to 'drivers/cpufreq/kirkwood-cpufreq.c')
-rw-r--r-- | drivers/cpufreq/kirkwood-cpufreq.c | 107 |
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 | ||
58 | static void kirkwood_cpufreq_set_cpu_state(struct cpufreq_policy *policy, | 58 | static 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 | |||
105 | static int kirkwood_cpufreq_verify(struct cpufreq_policy *policy) | ||
106 | { | ||
107 | return cpufreq_frequency_table_verify(policy, kirkwood_freq_table); | ||
108 | } | ||
109 | 79 | ||
110 | static 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 */ |
126 | static int kirkwood_cpufreq_cpu_init(struct cpufreq_policy *policy) | 94 | static 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 | |||
143 | static 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 | ||
149 | static struct freq_attr *kirkwood_cpufreq_attr[] = { | ||
150 | &cpufreq_freq_attr_scaling_available_freqs, | ||
151 | NULL, | ||
152 | }; | ||
153 | |||
154 | static struct cpufreq_driver kirkwood_cpufreq_driver = { | 99 | static 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 | ||
164 | static int kirkwood_cpufreq_probe(struct platform_device *pdev) | 109 | static int kirkwood_cpufreq_probe(struct platform_device *pdev) |