OpenCores
URL https://opencores.org/ocsvn/or1k_soc_on_altera_embedded_dev_kit/or1k_soc_on_altera_embedded_dev_kit/trunk

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [linux-2.6/] [linux-2.6.24/] [arch/] [sparc64/] [kernel/] [us3_cpufreq.c] - Blame information for rev 3

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 xianfeng
/* us3_cpufreq.c: UltraSPARC-III cpu frequency support
2
 *
3
 * Copyright (C) 2003 David S. Miller (davem@redhat.com)
4
 *
5
 * Many thanks to Dominik Brodowski for fixing up the cpufreq
6
 * infrastructure in order to make this driver easier to implement.
7
 */
8
 
9
#include <linux/kernel.h>
10
#include <linux/module.h>
11
#include <linux/sched.h>
12
#include <linux/smp.h>
13
#include <linux/cpufreq.h>
14
#include <linux/threads.h>
15
#include <linux/slab.h>
16
#include <linux/init.h>
17
 
18
#include <asm/head.h>
19
#include <asm/timer.h>
20
 
21
static struct cpufreq_driver *cpufreq_us3_driver;
22
 
23
struct us3_freq_percpu_info {
24
        struct cpufreq_frequency_table table[4];
25
};
26
 
27
/* Indexed by cpu number. */
28
static struct us3_freq_percpu_info *us3_freq_table;
29
 
30
/* UltraSPARC-III has three dividers: 1, 2, and 32.  These are controlled
31
 * in the Safari config register.
32
 */
33
#define SAFARI_CFG_DIV_1        0x0000000000000000UL
34
#define SAFARI_CFG_DIV_2        0x0000000040000000UL
35
#define SAFARI_CFG_DIV_32       0x0000000080000000UL
36
#define SAFARI_CFG_DIV_MASK     0x00000000C0000000UL
37
 
38
static unsigned long read_safari_cfg(void)
39
{
40
        unsigned long ret;
41
 
42
        __asm__ __volatile__("ldxa      [%%g0] %1, %0"
43
                             : "=&r" (ret)
44
                             : "i" (ASI_SAFARI_CONFIG));
45
        return ret;
46
}
47
 
48
static void write_safari_cfg(unsigned long val)
49
{
50
        __asm__ __volatile__("stxa      %0, [%%g0] %1\n\t"
51
                             "membar    #Sync"
52
                             : /* no outputs */
53
                             : "r" (val), "i" (ASI_SAFARI_CONFIG)
54
                             : "memory");
55
}
56
 
57
static unsigned long get_current_freq(unsigned int cpu, unsigned long safari_cfg)
58
{
59
        unsigned long clock_tick = sparc64_get_clock_tick(cpu) / 1000;
60
        unsigned long ret;
61
 
62
        switch (safari_cfg & SAFARI_CFG_DIV_MASK) {
63
        case SAFARI_CFG_DIV_1:
64
                ret = clock_tick / 1;
65
                break;
66
        case SAFARI_CFG_DIV_2:
67
                ret = clock_tick / 2;
68
                break;
69
        case SAFARI_CFG_DIV_32:
70
                ret = clock_tick / 32;
71
                break;
72
        default:
73
                BUG();
74
        };
75
 
76
        return ret;
77
}
78
 
79
static unsigned int us3_freq_get(unsigned int cpu)
80
{
81
        cpumask_t cpus_allowed;
82
        unsigned long reg;
83
        unsigned int ret;
84
 
85
        if (!cpu_online(cpu))
86
                return 0;
87
 
88
        cpus_allowed = current->cpus_allowed;
89
        set_cpus_allowed(current, cpumask_of_cpu(cpu));
90
 
91
        reg = read_safari_cfg();
92
        ret = get_current_freq(cpu, reg);
93
 
94
        set_cpus_allowed(current, cpus_allowed);
95
 
96
        return ret;
97
}
98
 
99
static void us3_set_cpu_divider_index(unsigned int cpu, unsigned int index)
100
{
101
        unsigned long new_bits, new_freq, reg;
102
        cpumask_t cpus_allowed;
103
        struct cpufreq_freqs freqs;
104
 
105
        if (!cpu_online(cpu))
106
                return;
107
 
108
        cpus_allowed = current->cpus_allowed;
109
        set_cpus_allowed(current, cpumask_of_cpu(cpu));
110
 
111
        new_freq = sparc64_get_clock_tick(cpu) / 1000;
112
        switch (index) {
113
        case 0:
114
                new_bits = SAFARI_CFG_DIV_1;
115
                new_freq /= 1;
116
                break;
117
        case 1:
118
                new_bits = SAFARI_CFG_DIV_2;
119
                new_freq /= 2;
120
                break;
121
        case 2:
122
                new_bits = SAFARI_CFG_DIV_32;
123
                new_freq /= 32;
124
                break;
125
 
126
        default:
127
                BUG();
128
        };
129
 
130
        reg = read_safari_cfg();
131
 
132
        freqs.old = get_current_freq(cpu, reg);
133
        freqs.new = new_freq;
134
        freqs.cpu = cpu;
135
        cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
136
 
137
        reg &= ~SAFARI_CFG_DIV_MASK;
138
        reg |= new_bits;
139
        write_safari_cfg(reg);
140
 
141
        cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
142
 
143
        set_cpus_allowed(current, cpus_allowed);
144
}
145
 
146
static int us3_freq_target(struct cpufreq_policy *policy,
147
                          unsigned int target_freq,
148
                          unsigned int relation)
149
{
150
        unsigned int new_index = 0;
151
 
152
        if (cpufreq_frequency_table_target(policy,
153
                                           &us3_freq_table[policy->cpu].table[0],
154
                                           target_freq,
155
                                           relation,
156
                                           &new_index))
157
                return -EINVAL;
158
 
159
        us3_set_cpu_divider_index(policy->cpu, new_index);
160
 
161
        return 0;
162
}
163
 
164
static int us3_freq_verify(struct cpufreq_policy *policy)
165
{
166
        return cpufreq_frequency_table_verify(policy,
167
                                              &us3_freq_table[policy->cpu].table[0]);
168
}
169
 
170
static int __init us3_freq_cpu_init(struct cpufreq_policy *policy)
171
{
172
        unsigned int cpu = policy->cpu;
173
        unsigned long clock_tick = sparc64_get_clock_tick(cpu) / 1000;
174
        struct cpufreq_frequency_table *table =
175
                &us3_freq_table[cpu].table[0];
176
 
177
        table[0].index = 0;
178
        table[0].frequency = clock_tick / 1;
179
        table[1].index = 1;
180
        table[1].frequency = clock_tick / 2;
181
        table[2].index = 2;
182
        table[2].frequency = clock_tick / 32;
183
        table[3].index = 0;
184
        table[3].frequency = CPUFREQ_TABLE_END;
185
 
186
        policy->governor = CPUFREQ_DEFAULT_GOVERNOR;
187
        policy->cpuinfo.transition_latency = 0;
188
        policy->cur = clock_tick;
189
 
190
        return cpufreq_frequency_table_cpuinfo(policy, table);
191
}
192
 
193
static int us3_freq_cpu_exit(struct cpufreq_policy *policy)
194
{
195
        if (cpufreq_us3_driver)
196
                us3_set_cpu_divider_index(policy->cpu, 0);
197
 
198
        return 0;
199
}
200
 
201
static int __init us3_freq_init(void)
202
{
203
        unsigned long manuf, impl, ver;
204
        int ret;
205
 
206
        if (tlb_type != cheetah && tlb_type != cheetah_plus)
207
                return -ENODEV;
208
 
209
        __asm__("rdpr %%ver, %0" : "=r" (ver));
210
        manuf = ((ver >> 48) & 0xffff);
211
        impl  = ((ver >> 32) & 0xffff);
212
 
213
        if (manuf == CHEETAH_MANUF &&
214
            (impl == CHEETAH_IMPL ||
215
             impl == CHEETAH_PLUS_IMPL ||
216
             impl == JAGUAR_IMPL ||
217
             impl == PANTHER_IMPL)) {
218
                struct cpufreq_driver *driver;
219
 
220
                ret = -ENOMEM;
221
                driver = kzalloc(sizeof(struct cpufreq_driver), GFP_KERNEL);
222
                if (!driver)
223
                        goto err_out;
224
 
225
                us3_freq_table = kzalloc(
226
                        (NR_CPUS * sizeof(struct us3_freq_percpu_info)),
227
                        GFP_KERNEL);
228
                if (!us3_freq_table)
229
                        goto err_out;
230
 
231
                driver->init = us3_freq_cpu_init;
232
                driver->verify = us3_freq_verify;
233
                driver->target = us3_freq_target;
234
                driver->get = us3_freq_get;
235
                driver->exit = us3_freq_cpu_exit;
236
                driver->owner = THIS_MODULE,
237
                strcpy(driver->name, "UltraSPARC-III");
238
 
239
                cpufreq_us3_driver = driver;
240
                ret = cpufreq_register_driver(driver);
241
                if (ret)
242
                        goto err_out;
243
 
244
                return 0;
245
 
246
err_out:
247
                if (driver) {
248
                        kfree(driver);
249
                        cpufreq_us3_driver = NULL;
250
                }
251
                kfree(us3_freq_table);
252
                us3_freq_table = NULL;
253
                return ret;
254
        }
255
 
256
        return -ENODEV;
257
}
258
 
259
static void __exit us3_freq_exit(void)
260
{
261
        if (cpufreq_us3_driver) {
262
                cpufreq_unregister_driver(cpufreq_us3_driver);
263
                kfree(cpufreq_us3_driver);
264
                cpufreq_us3_driver = NULL;
265
                kfree(us3_freq_table);
266
                us3_freq_table = NULL;
267
        }
268
}
269
 
270
MODULE_AUTHOR("David S. Miller <davem@redhat.com>");
271
MODULE_DESCRIPTION("cpufreq driver for UltraSPARC-III");
272
MODULE_LICENSE("GPL");
273
 
274
module_init(us3_freq_init);
275
module_exit(us3_freq_exit);

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.